]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cache_cf.cc
Sync store meta assignments with Squid-2.
[thirdparty/squid.git] / src / cache_cf.cc
CommitLineData
be335c22 1
30a4f2a8 2/*
f41735ea 3 * $Id: cache_cf.cc,v 1.528 2007/11/15 23:33:05 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 3 Configuration File Parsing
6 * AUTHOR: Harvest Derived
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
30a4f2a8 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
30a4f2a8 34 */
cf5fd929 35
44a47c6e 36#include "squid.h"
e6ccf245 37#include "authenticate.h"
f5691f9c 38#include "AuthConfig.h"
39#include "AuthScheme.h"
62ee09ca 40#include "CacheManager.h"
e6ccf245 41#include "Store.h"
d3b3ab85 42#include "SwapDir.h"
a80a77cf 43#include "ConfigParser.h"
8000a965 44#include "ACL.h"
59b2d47f 45#include "StoreFileSystem.h"
c8f4eac4 46#include "Parsing.h"
0eb49b6d 47#include "MemBuf.h"
d295d770 48#include "wordlist.h"
1df370e3 49
50#if SQUID_SNMP
a97cfa48 51#include "snmp.h"
1df370e3 52#endif
f41735ea 53#if USE_SQUID_ESI
43ae1d95 54#include "ESIParser.h"
55#endif
090089c4 56
3a69ddf3 57#if ICAP_CLIENT
58#include "ICAP/ICAPConfig.h"
3a69ddf3 59
60static void parse_icap_service_type(ICAPConfig *);
a99015b2 61static void dump_icap_service_type(StoreEntry *, const char *, const ICAPConfig &);
3a69ddf3 62static void free_icap_service_type(ICAPConfig *);
63static void parse_icap_class_type(ICAPConfig *);
a99015b2 64static void dump_icap_class_type(StoreEntry *, const char *, const ICAPConfig &);
3a69ddf3 65static void free_icap_class_type(ICAPConfig *);
66static void parse_icap_access_type(ICAPConfig *);
a99015b2 67static void dump_icap_access_type(StoreEntry *, const char *, const ICAPConfig &);
3a69ddf3 68static void free_icap_access_type(ICAPConfig *);
69
70#endif
71
f5691f9c 72CBDATA_TYPE(peer);
73
8813e606 74static const char *const T_SECOND_STR = "second";
75static const char *const T_MINUTE_STR = "minute";
76static const char *const T_HOUR_STR = "hour";
77static const char *const T_DAY_STR = "day";
78static const char *const T_WEEK_STR = "week";
79static const char *const T_FORTNIGHT_STR = "fortnight";
80static const char *const T_MONTH_STR = "month";
81static const char *const T_YEAR_STR = "year";
82static const char *const T_DECADE_STR = "decade";
aa0a0c7c 83
9906e724 84static const char *const B_BYTES_STR = "bytes";
85static const char *const B_KBYTES_STR = "KB";
86static const char *const B_MBYTES_STR = "MB";
87static const char *const B_GBYTES_STR = "GB";
88
4db43fab 89static const char *const list_sep = ", \t\n\r";
b0e7d2d5 90
7684c4b1 91static void parse_logformat(logformat ** logformat_definitions);
92static void parse_access_log(customlog ** customlog_definitions);
ca801547 93#if UNUSED_CODE
d64bef4c 94static int check_null_access_log(customlog *customlog_definitions);
ca801547 95#endif
d64bef4c 96
7684c4b1 97static void dump_logformat(StoreEntry * entry, const char *name, logformat * definitions);
98static void dump_access_log(StoreEntry * entry, const char *name, customlog * definitions);
99static void free_logformat(logformat ** definitions);
100static void free_access_log(customlog ** definitions);
101
cd748f27 102static void update_maxobjsize(void);
f5b8bbc4 103static void configDoConfigure(void);
104static void parse_refreshpattern(refresh_t **);
105static int parseTimeUnits(const char *unit);
106static void parseTimeLine(time_t * tptr, const char *units);
59715b38 107static void parse_ushort(u_short * var);
f5b8bbc4 108static void parse_string(char **);
f5b8bbc4 109static void default_all(void);
110static void defaults_if_none(void);
111static int parse_line(char *);
112static void parseBytesLine(size_t * bptr, const char *units);
113static size_t parseBytesUnits(const char *unit);
f5b8bbc4 114static void free_all(void);
94439e4e 115void requirePathnameExists(const char *name, const char *path);
ed7f5615 116static OBJH dump_config;
c26ffae9 117#if HTTP_VIOLATIONS
6bccf575 118static void dump_http_header_access(StoreEntry * entry, const char *name, header_mangler header[]);
119static void parse_http_header_access(header_mangler header[]);
120static void free_http_header_access(header_mangler header[]);
121static void dump_http_header_replace(StoreEntry * entry, const char *name, header_mangler header[]);
122static void parse_http_header_replace(header_mangler * header);
123static void free_http_header_replace(header_mangler * header);
9e8b2f1c 124#endif
6bccf575 125static void parse_denyinfo(acl_deny_info_list ** var);
126static void dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var);
127static void free_denyinfo(acl_deny_info_list ** var);
e1a88700 128
0b0cfcf2 129#if USE_WCCPv2
7e3ce7b9 130static void parse_sockaddr_in_list(sockaddr_in_list **);
131static void dump_sockaddr_in_list(StoreEntry *, const char *, const sockaddr_in_list *);
132static void free_sockaddr_in_list(sockaddr_in_list **);
0b0cfcf2 133#if CURRENTLY_UNUSED
7e3ce7b9 134static int check_null_sockaddr_in_list(const sockaddr_in_list *);
3f38a55e 135#endif /* CURRENTLY_UNUSED */
e1a88700 136#endif /* USE_WCCPv2 */
137
3f38a55e 138static void parse_http_port_list(http_port_list **);
139static void dump_http_port_list(StoreEntry *, const char *, const http_port_list *);
140static void free_http_port_list(http_port_list **);
e1a88700 141
d193a436 142#if USE_SSL
143static void parse_https_port_list(https_port_list **);
144static void dump_https_port_list(StoreEntry *, const char *, const https_port_list *);
145static void free_https_port_list(https_port_list **);
146#if 0
147static int check_null_https_port_list(const https_port_list *);
148#endif
149#endif /* USE_SSL */
e1a88700 150
ef1955a5 151static void parse_b_size_t(size_t * var);
47f6e231 152static void parse_b_int64_t(int64_t * var);
270b86af 153
a385afc3 154/*
155 * LegacyParser is a parser for legacy code that uses the global
156 * approach. This is static so that it is only exposed to cache_cf.
157 * Other modules needing access to a ConfigParser should have it
158 * provided to them in their parserFOO methods.
159 */
160static ConfigParser LegacyParser = ConfigParser();
a9f20260 161
0e4e0e7d 162void
0673c0ba 163self_destruct(void)
090089c4 164{
a9f20260 165 LegacyParser.destruct();
6b8e7481 166}
167
cd748f27 168static void
169update_maxobjsize(void)
170{
171 int i;
47f6e231 172 int64_t ms = -1;
cd748f27 173
174 for (i = 0; i < Config.cacheSwap.n_configured; i++) {
c8f4eac4 175 assert (Config.cacheSwap.swapDirs[i].getRaw());
62e76326 176
c8f4eac4 177 if (dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->
178 max_objsize > ms)
179 ms = dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->max_objsize;
cd748f27 180 }
181 store_maxobjsize = ms;
182}
183
76b9daa5 184static void
185SetConfigFilename(char const *file_name, bool is_pipe)
186{
187 cfg_filename = file_name;
188
189 char const *token;
190
191 if (is_pipe)
192 cfg_filename = file_name + 1;
193 else if ((token = strrchr(cfg_filename, '/')))
194 cfg_filename = token + 1;
195}
196
130bff33 197static const char*
198skip_ws(const char* s)
199{
200 while (xisspace(*s))
201 ++s;
202
203 return s;
204}
205
270b86af 206int
62ee09ca 207parseConfigFile(const char *file_name, CacheManager & manager)
2546fcb3 208{
270b86af 209 FILE *fp = NULL;
210 char *token = NULL;
81c161d0 211 char *tmp_line = NULL;
212 int tmp_line_len = 0;
e13ee7ad 213 int err_count = 0;
1741cbad 214 int is_pipe = 0;
42bf7c64 215 configFreeMemory();
0153d498 216 default_all();
62e76326 217
1741cbad 218 if (file_name[0] == '!' || file_name[0] == '|') {
62e76326 219 fp = popen(file_name + 1, "r");
220 is_pipe = 1;
1741cbad 221 } else {
62e76326 222 fp = fopen(file_name, "r");
1741cbad 223 }
62e76326 224
1741cbad 225 if (fp == NULL)
62e76326 226 fatalf("Unable to open configuration file: %s: %s",
227 file_name, xstrerror());
228
ec4daaa5 229#ifdef _SQUID_WIN32_
62e76326 230
c4aefe96 231 setmode(fileno(fp), O_TEXT);
62e76326 232
c4aefe96 233#endif
62e76326 234
76b9daa5 235 SetConfigFilename(file_name, bool(is_pipe));
62e76326 236
270b86af 237 memset(config_input_line, '\0', BUFSIZ);
62e76326 238
270b86af 239 config_lineno = 0;
62e76326 240
270b86af 241 while (fgets(config_input_line, BUFSIZ, fp)) {
62e76326 242 config_lineno++;
243
244 if ((token = strchr(config_input_line, '\n')))
245 *token = '\0';
246
d866e2ad 247 if ((token = strchr(config_input_line, '\r')))
248 *token = '\0';
249
62e76326 250 if (strncmp(config_input_line, "#line ", 6) == 0) {
251 static char new_file_name[1024];
252 static char *file;
253 static char new_lineno;
254 token = config_input_line + 6;
255 new_lineno = strtol(token, &file, 0) - 1;
256
257 if (file == token)
258 continue; /* Not a valid #line directive, may be a comment */
259
e4755e29 260 while (*file && xisspace((unsigned char) *file))
62e76326 261 file++;
262
263 if (*file) {
264 if (*file != '"')
265 continue; /* Not a valid #line directive, may be a comment */
266
267 xstrncpy(new_file_name, file + 1, sizeof(new_file_name));
268
269 if ((token = strchr(new_file_name, '"')))
270 *token = '\0';
271
272 cfg_filename = new_file_name;
273
1741cbad 274#if PROBABLY_NOT_WANTED_HERE
62e76326 275
76b9daa5 276 SetConfigFilename(cfg_filename, false);
62e76326 277
1741cbad 278#endif
62e76326 279
280 }
281
282 config_lineno = new_lineno;
283 }
284
285 if (config_input_line[0] == '#')
286 continue;
287
288 if (config_input_line[0] == '\0')
289 continue;
290
130bff33 291 const char* append = tmp_line_len ? skip_ws(config_input_line) : config_input_line;
292
293 size_t append_len = strlen(append);
62e76326 294
130bff33 295 tmp_line = (char*)xrealloc(tmp_line, tmp_line_len + append_len + 1);
81c161d0 296
130bff33 297 strcpy(tmp_line + tmp_line_len, append);
81c161d0 298
130bff33 299 tmp_line_len += append_len;
81c161d0 300
301 if (tmp_line[tmp_line_len-1] == '\\') {
bf8fe701 302 debugs(3, 5, "parseConfigFile: tmp_line='" << tmp_line << "'");
81c161d0 303 tmp_line[--tmp_line_len] = '\0';
304 continue;
305 }
306
bf8fe701 307 debugs(3, 5, "Processing: '" << tmp_line << "'");
62e76326 308
309 if (!parse_line(tmp_line)) {
bf8fe701 310 debugs(3, 0, "parseConfigFile: '" << cfg_filename << "' line " <<
311 config_lineno << " unrecognized: '" << config_input_line << "'");
62e76326 312 err_count++;
313 }
314
315 safe_free(tmp_line);
81c161d0 316 tmp_line_len = 0;
317
270b86af 318 }
62e76326 319
1741cbad 320 if (is_pipe) {
62e76326 321 int ret = pclose(fp);
322
323 if (ret != 0)
324 fatalf("parseConfigFile: '%s' failed with exit code %d\n", file_name, ret);
1741cbad 325 } else {
62e76326 326 fclose(fp);
1741cbad 327 }
62e76326 328
f0b19334 329 defaults_if_none();
f9ad0106 330
9c46ca97 331 /*
332 * We must call configDoConfigure() before leave_suid() because
333 * configDoConfigure() is where we turn username strings into
334 * uid values.
335 */
336 configDoConfigure();
337
f9ad0106 338 if (!Config.chroot_dir) {
339 leave_suid();
340 _db_init(Config.Log.log, Config.debugOptions);
341 enter_suid();
342 }
343
478c4f2f 344 if (opt_send_signal == -1) {
62ee09ca 345 manager.registerAction("config",
346 "Current Squid Configuration",
347 dump_config,
348 1, 1);
478c4f2f 349 }
350
e13ee7ad 351 return err_count;
f0b19334 352}
270b86af 353
f0b19334 354static void
355configDoConfigure(void)
356{
f0b19334 357 memset(&Config2, '\0', sizeof(SquidConfig2));
7021844c 358 /* init memory as early as possible */
359 memConfigure();
270b86af 360 /* Sanity checks */
62e76326 361
a95856a0 362 if (Config.cacheSwap.swapDirs == NULL)
62e76326 363 fatal("No cache_dir's specified in config file");
364
5aecb102 365#if SIZEOF_OFF_T <= 4
366 if (Config.Store.maxObjectSize > 0x7FFF0000) {
367 debugs(3, 0, "WARNING: This Squid binary can not handle files larger than 2GB. Limiting maximum_object_size to just below 2GB");
368 Config.Store.maxObjectSize = 0x7FFF0000;
369 }
370#endif
c8f4eac4 371 if (0 == Store::Root().maxSize())
62e76326 372 /* people might want a zero-sized cache on purpose */
373 (void) 0;
c8f4eac4 374 else if (Store::Root().maxSize() < (Config.memMaxSize >> 10))
375 /* This is bogus. folk with NULL caches will want this */
bf8fe701 376 debugs(3, 0, "WARNING cache_mem is larger than total disk cache space!");
62e76326 377
84f42bac 378 if (Config.Announce.period > 0) {
62e76326 379 Config.onoff.announce = 1;
84f42bac 380 } else if (Config.Announce.period < 1) {
62e76326 381 Config.Announce.period = 86400 * 365; /* one year */
382 Config.onoff.announce = 0;
270b86af 383 }
62e76326 384
d3caee79 385 if (Config.onoff.httpd_suppress_version_string)
386 visible_appname_string = (char *)appname_string;
387 else
388 visible_appname_string = (char *)full_appname_string;
389
6b53c392 390#if USE_DNSSERVERS
d3caee79 391
f0b19334 392 if (Config.dnsChildren < 1)
62e76326 393 fatal("No dnsservers allocated");
394
efd900cb 395#endif
62e76326 396
270b86af 397 if (Config.Program.redirect) {
62e76326 398 if (Config.redirectChildren < 1) {
399 Config.redirectChildren = 0;
400 wordlistDestroy(&Config.Program.redirect);
401 }
fea2e6e0 402 }
62e76326 403
f1dc9b30 404 if (Config.appendDomain)
62e76326 405 if (*Config.appendDomain != '.')
406 fatal("append_domain must begin with a '.'");
407
270b86af 408 if (Config.errHtmlText == NULL)
62e76326 409 Config.errHtmlText = xstrdup(null_string);
410
270b86af 411 storeConfigure();
62e76326 412
52f772de 413 snprintf(ThisCache, sizeof(ThisCache), "%s (%s)",
62e76326 414 uniqueHostname(),
d3caee79 415 visible_appname_string);
fbdba7c4 416
38a6c74e 417 /*
418 * the extra space is for loop detection in client_side.c -- we search
419 * for substrings in the Via header.
420 */
52f772de 421 snprintf(ThisCache2, sizeof(ThisCache), " %s (%s)",
62e76326 422 uniqueHostname(),
d3caee79 423 visible_appname_string);
62e76326 424
270b86af 425 if (!Config.udpMaxHitObjsz || Config.udpMaxHitObjsz > SQUID_UDP_SO_SNDBUF)
62e76326 426 Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF;
427
270b86af 428 if (Config.appendDomain)
62e76326 429 Config.appendDomainLen = strlen(Config.appendDomain);
270b86af 430 else
62e76326 431 Config.appendDomainLen = 0;
432
f1dc9b30 433 safe_free(debug_options)
62e76326 434 debug_options = xstrdup(Config.debugOptions);
435
22c653cd 436 if (Config.retry.maxtries > 10)
62e76326 437 fatal("maximum_single_addr_tries cannot be larger than 10");
438
22c653cd 439 if (Config.retry.maxtries < 1) {
bf8fe701 440 debugs(3, 0, "WARNING: resetting 'maximum_single_addr_tries to 1");
62e76326 441 Config.retry.maxtries = 1;
5210854d 442 }
62e76326 443
f0b19334 444 requirePathnameExists("MIME Config Table", Config.mimeTablePathname);
6b53c392 445#if USE_DNSSERVERS
62e76326 446
f0b19334 447 requirePathnameExists("cache_dns_program", Config.Program.dnsserver);
efd900cb 448#endif
a3d0a19d 449#if USE_UNLINKD
62e76326 450
f0b19334 451 requirePathnameExists("unlinkd_program", Config.Program.unlinkd);
a3d0a19d 452#endif
62e76326 453
f0b19334 454 if (Config.Program.redirect)
62e76326 455 requirePathnameExists("redirect_program", Config.Program.redirect->key);
456
f0b19334 457 requirePathnameExists("Icon Directory", Config.icons.directory);
62e76326 458
f0b19334 459 requirePathnameExists("Error Directory", Config.errorDirectory);
62e76326 460
9f60cfdf 461#if HTTP_VIOLATIONS
62e76326 462
9f60cfdf 463 {
62e76326 464 const refresh_t *R;
465
466 for (R = Config.Refresh; R; R = R->next)
467 {
468 if (!R->flags.override_expire)
469 continue;
470
bf8fe701 471 debugs(22, 1, "WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP");
62e76326 472
473 break;
474 }
475
476 for (R = Config.Refresh; R; R = R->next)
477 {
478 if (!R->flags.override_lastmod)
479 continue;
480
bf8fe701 481 debugs(22, 1, "WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP");
62e76326 482
483 break;
484 }
485
38f9c547 486 for (R = Config.Refresh; R; R = R->next)
487 {
488 if (!R->flags.reload_into_ims)
489 continue;
490
bf8fe701 491 debugs(22, 1, "WARNING: use of 'reload-into-ims' in 'refresh_pattern' violates HTTP");
38f9c547 492
493 break;
494 }
495
496 for (R = Config.Refresh; R; R = R->next)
497 {
498 if (!R->flags.ignore_reload)
499 continue;
500
bf8fe701 501 debugs(22, 1, "WARNING: use of 'ignore-reload' in 'refresh_pattern' violates HTTP");
38f9c547 502
503 break;
504 }
505
506 for (R = Config.Refresh; R; R = R->next)
507 {
508 if (!R->flags.ignore_no_cache)
509 continue;
510
bf8fe701 511 debugs(22, 1, "WARNING: use of 'ignore-no-cache' in 'refresh_pattern' violates HTTP");
38f9c547 512
513 break;
514 }
515
516 for (R = Config.Refresh; R; R = R->next)
517 {
518 if (!R->flags.ignore_no_store)
519 continue;
520
bf8fe701 521 debugs(22, 1, "WARNING: use of 'ignore-no-store' in 'refresh_pattern' violates HTTP");
38f9c547 522
523 break;
524 }
525
526 for (R = Config.Refresh; R; R = R->next)
527 {
528 if (!R->flags.ignore_private)
529 continue;
530
bf8fe701 531 debugs(22, 1, "WARNING: use of 'ignore-private' in 'refresh_pattern' violates HTTP");
38f9c547 532
533 break;
534 }
535
536 for (R = Config.Refresh; R; R = R->next)
537 {
538 if (!R->flags.ignore_auth)
539 continue;
540
bf8fe701 541 debugs(22, 1, "WARNING: use of 'ignore-auth' in 'refresh_pattern' violates HTTP");
38f9c547 542
543 break;
544 }
545
9f60cfdf 546 }
c2f5c744 547#endif
548#if !HTTP_VIOLATIONS
549 Config.onoff.via = 1;
550#else
62e76326 551
c2f5c744 552 if (!Config.onoff.via)
bf8fe701 553 debugs(22, 1, "WARNING: HTTP requires the use of Via");
62e76326 554
9f60cfdf 555#endif
62e76326 556
53cb32a9 557 if (aclPurgeMethodInUse(Config.accessList.http))
62e76326 558 Config2.onoff.enable_purge = 1;
559
4f56514c 560 Config2.onoff.mangle_request_headers = httpReqHdrManglersConfigured();
5967c0bf 561
8749fa47 562 if (geteuid() == 0) {
62e76326 563 if (NULL != Config.effectiveUser) {
564
565 struct passwd *pwd = getpwnam(Config.effectiveUser);
566
5ad8d199 567 if (NULL == pwd) {
62e76326 568 /*
569 * Andres Kroonmaa <andre@online.ee>:
570 * Some getpwnam() implementations (Solaris?) require
571 * an available FD < 256 for opening a FILE* to the
572 * passwd file.
573 * DW:
574 * This should be safe at startup, but might still fail
575 * during reconfigure.
576 */
577 fatalf("getpwnam failed to find userid for effective user '%s'",
578 Config.effectiveUser);
5ad8d199 579 return;
580 }
62e76326 581
582 Config2.effectiveUserID = pwd->pw_uid;
583
584 Config2.effectiveGroupID = pwd->pw_gid;
08ac5ea7 585
cff61cb8 586#if HAVE_PUTENV
587
588 if (pwd->pw_dir && *pwd->pw_dir) {
589 int len;
590 char *env_str = (char *)xcalloc((len = strlen(pwd->pw_dir) + 6), 1);
591 snprintf(env_str, len, "HOME=%s", pwd->pw_dir);
592 putenv(env_str);
593 }
594
595#endif
596
62e76326 597 }
8749fa47 598 } else {
62e76326 599 Config2.effectiveUserID = geteuid();
600 Config2.effectiveGroupID = getegid();
d20b1cd0 601 }
62e76326 602
d20b1cd0 603 if (NULL != Config.effectiveGroup) {
62e76326 604
605 struct group *grp = getgrnam(Config.effectiveGroup);
606
5ad8d199 607 if (NULL == grp) {
62e76326 608 fatalf("getgrnam failed to find groupid for effective group '%s'",
609 Config.effectiveGroup);
5ad8d199 610 return;
611 }
62e76326 612
613 Config2.effectiveGroupID = grp->gr_gid;
d20b1cd0 614 }
62e76326 615
985c86bc 616 HttpRequestMethod::Configure(Config);
a7ad6e4e 617#if USE_SSL
62e76326 618
bf8fe701 619 debugs(3, 1, "Initializing https proxy context");
f9ad0106 620
a82a4fe4 621 Config.ssl_client.sslContext = sslCreateClientContext(Config.ssl_client.cert, Config.ssl_client.key, Config.ssl_client.version, Config.ssl_client.cipher, Config.ssl_client.options, Config.ssl_client.flags, Config.ssl_client.cafile, Config.ssl_client.capath, Config.ssl_client.crlfile);
f9ad0106 622
623 {
624
625 peer *p;
626
627 for (p = Config.peers; p != NULL; p = p->next) {
628 if (p->use_ssl) {
bf8fe701 629 debugs(3, 1, "Initializing cache_peer " << p->name << " SSL context");
a82a4fe4 630 p->sslContext = sslCreateClientContext(p->sslcert, p->sslkey, p->sslversion, p->sslcipher, p->ssloptions, p->sslflags, p->sslcafile, p->sslcapath, p->sslcrlfile);
f9ad0106 631 }
632 }
633 }
634
635 {
636
637 https_port_list *s;
638
b844522c 639 for (s = Config.Sockaddr.https; s != NULL; s = (https_port_list *) s->http.next) {
bf8fe701 640 debugs(3, 1, "Initializing https_port " <<
641 inet_ntoa(s->http.s.sin_addr) << ":" <<
642 ntohs(s->http.s.sin_port) << " SSL context");
643
a82a4fe4 644 s->sslContext = sslCreateServerContext(s->cert, s->key, s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath, s->crlfile, s->dhfile, s->sslcontext);
f9ad0106 645 }
646 }
647
a7ad6e4e 648#endif
090089c4 649}
650
270b86af 651/* Parse a time specification from the config file. Store the
f1dc9b30 652 * result in 'tptr', after converting it to 'units' */
8203a132 653static void
a47b9029 654parseTimeLine(time_t * tptr, const char *units)
090089c4 655{
656 char *token;
270b86af 657 double d;
f1dc9b30 658 time_t m;
659 time_t u;
62e76326 660
270b86af 661 if ((u = parseTimeUnits(units)) == 0)
62e76326 662 self_destruct();
663
270b86af 664 if ((token = strtok(NULL, w_space)) == NULL)
62e76326 665 self_destruct();
666
5c20d6fa 667 d = xatof(token);
62e76326 668
270b86af 669 m = u; /* default to 'units' if none specified */
62e76326 670
10738561 671 if (0 == d)
62e76326 672 (void) 0;
10738561 673 else if ((token = strtok(NULL, w_space)) == NULL)
bf8fe701 674 debugs(3, 0, "WARNING: No units on '" <<
675 config_input_line << "', assuming " <<
676 d << " " << units );
9e975e4e 677 else if ((m = parseTimeUnits(token)) == 0)
62e76326 678 self_destruct();
679
e6ccf245 680 *tptr = static_cast<time_t> (m * d / u);
090089c4 681}
682
270b86af 683static int
684parseTimeUnits(const char *unit)
685{
686 if (!strncasecmp(unit, T_SECOND_STR, strlen(T_SECOND_STR)))
62e76326 687 return 1;
688
270b86af 689 if (!strncasecmp(unit, T_MINUTE_STR, strlen(T_MINUTE_STR)))
62e76326 690 return 60;
691
270b86af 692 if (!strncasecmp(unit, T_HOUR_STR, strlen(T_HOUR_STR)))
62e76326 693 return 3600;
694
270b86af 695 if (!strncasecmp(unit, T_DAY_STR, strlen(T_DAY_STR)))
62e76326 696 return 86400;
697
270b86af 698 if (!strncasecmp(unit, T_WEEK_STR, strlen(T_WEEK_STR)))
62e76326 699 return 86400 * 7;
700
270b86af 701 if (!strncasecmp(unit, T_FORTNIGHT_STR, strlen(T_FORTNIGHT_STR)))
62e76326 702 return 86400 * 14;
703
270b86af 704 if (!strncasecmp(unit, T_MONTH_STR, strlen(T_MONTH_STR)))
62e76326 705 return 86400 * 30;
706
270b86af 707 if (!strncasecmp(unit, T_YEAR_STR, strlen(T_YEAR_STR)))
62e76326 708 return static_cast<int>(86400 * 365.2522);
709
270b86af 710 if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR)))
62e76326 711 return static_cast<int>(86400 * 365.2522 * 10);
712
bf8fe701 713 debugs(3, 1, "parseTimeUnits: unknown time unit '" << unit << "'");
62e76326 714
270b86af 715 return 0;
716}
717
47f6e231 718static void
719parseBytesLine64(int64_t * bptr, const char *units)
720{
721 char *token;
722 double d;
723 int64_t m;
724 int64_t u;
725
9eeb8e4b 726 if ((u = parseBytesUnits(units)) == 0) {
47f6e231 727 self_destruct();
9eeb8e4b 728 return;
729 }
47f6e231 730
9eeb8e4b 731 if ((token = strtok(NULL, w_space)) == NULL) {
47f6e231 732 self_destruct();
9eeb8e4b 733 return;
734 }
47f6e231 735
736 if (strcmp(token, "none") == 0 || strcmp(token, "-1") == 0) {
bc41416d 737 *bptr = -1;
47f6e231 738 return;
739 }
740
741 d = xatof(token);
742
743 m = u; /* default to 'units' if none specified */
744
745 if (0.0 == d)
746 (void) 0;
747 else if ((token = strtok(NULL, w_space)) == NULL)
748 debugs(3, 0, "WARNING: No units on '" <<
749 config_input_line << "', assuming " <<
750 d << " " << units );
9eeb8e4b 751 else if ((m = parseBytesUnits(token)) == 0) {
47f6e231 752 self_destruct();
9eeb8e4b 753 return;
754 }
47f6e231 755
756 *bptr = static_cast<int64_t>(m * d / u);
757
758 if (static_cast<double>(*bptr) * 2 != m * d / u * 2)
759 self_destruct();
760}
761
762
9906e724 763static void
9e975e4e 764parseBytesLine(size_t * bptr, const char *units)
9906e724 765{
766 char *token;
767 double d;
47f6e231 768 int m;
769 int u;
62e76326 770
9eeb8e4b 771 if ((u = parseBytesUnits(units)) == 0) {
62e76326 772 self_destruct();
9eeb8e4b 773 return;
774 }
62e76326 775
9eeb8e4b 776 if ((token = strtok(NULL, w_space)) == NULL) {
62e76326 777 self_destruct();
9eeb8e4b 778 return;
779 }
62e76326 780
f8ecd7d7 781 if (strcmp(token, "none") == 0 || strcmp(token, "-1") == 0) {
b2d729e6 782 *bptr = static_cast<size_t>(-1);
ef1955a5 783 return;
784 }
785
5c20d6fa 786 d = xatof(token);
62e76326 787
9906e724 788 m = u; /* default to 'units' if none specified */
62e76326 789
343f47a3 790 if (0.0 == d)
62e76326 791 (void) 0;
4860dc1b 792 else if ((token = strtok(NULL, w_space)) == NULL)
bf8fe701 793 debugs(3, 0, "WARNING: No units on '" <<
794 config_input_line << "', assuming " <<
795 d << " " << units );
9eeb8e4b 796 else if ((m = parseBytesUnits(token)) == 0) {
62e76326 797 self_destruct();
9eeb8e4b 798 return;
799 }
62e76326 800
e6ccf245 801 *bptr = static_cast<size_t>(m * d / u);
347ae7c4 802
a69d485c 803 if (static_cast<double>(*bptr) * 2 != m * d / u * 2)
347ae7c4 804 self_destruct();
9906e724 805}
806
807static size_t
808parseBytesUnits(const char *unit)
809{
810 if (!strncasecmp(unit, B_BYTES_STR, strlen(B_BYTES_STR)))
62e76326 811 return 1;
812
9906e724 813 if (!strncasecmp(unit, B_KBYTES_STR, strlen(B_KBYTES_STR)))
62e76326 814 return 1 << 10;
815
9906e724 816 if (!strncasecmp(unit, B_MBYTES_STR, strlen(B_MBYTES_STR)))
62e76326 817 return 1 << 20;
818
9906e724 819 if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR)))
62e76326 820 return 1 << 30;
821
bf8fe701 822 debugs(3, 1, "parseBytesUnits: unknown bytes unit '" << unit << "'");
62e76326 823
9906e724 824 return 0;
825}
826
270b86af 827/*****************************************************************************
828 * Max
829 *****************************************************************************/
830
8203a132 831static void
97427e90 832dump_acl(StoreEntry * entry, const char *name, ACL * ae)
090089c4 833{
56b63fa1 834 wordlist *w;
835 wordlist *v;
62e76326 836
9ef28b60 837 while (ae != NULL) {
bf8fe701 838 debugs(3, 3, "dump_acl: " << name << " " << ae->name);
62e76326 839 storeAppendPrintf(entry, "%s %s %s ",
840 name,
841 ae->name,
842 ae->typeString());
6bf4f823 843 v = w = ae->dump();
62e76326 844
845 while (v != NULL) {
bf8fe701 846 debugs(3, 3, "dump_acl: " << name << " " << ae->name << " " << v->key);
62e76326 847 storeAppendPrintf(entry, "%s ", v->key);
848 v = v->next;
849 }
850
851 storeAppendPrintf(entry, "\n");
852 wordlistDestroy(&w);
853 ae = ae->next;
56b63fa1 854 }
090089c4 855}
856
8203a132 857static void
97427e90 858parse_acl(ACL ** ae)
090089c4 859{
a9f20260 860 ACL::ParseAclLine(LegacyParser, ae);
f1dc9b30 861}
862
863static void
97427e90 864free_acl(ACL ** ae)
f1dc9b30 865{
9ef28b60 866 aclDestroyAcls(ae);
090089c4 867}
868
8203a132 869static void
76cd39d7 870dump_acl_list(StoreEntry * entry, ACLList * head)
30a4f2a8 871{
76cd39d7 872 ACLList *l;
62e76326 873
d6827718 874 for (l = head; l; l = l->next) {
62e76326 875 storeAppendPrintf(entry, " %s%s",
876 l->op ? null_string : "!",
877 l->_acl->name);
d6827718 878 }
879}
880
b67e2c8c 881void
d6827718 882dump_acl_access(StoreEntry * entry, const char *name, acl_access * head)
883{
884 acl_access *l;
62e76326 885
d6827718 886 for (l = head; l; l = l->next) {
62e76326 887 storeAppendPrintf(entry, "%s %s",
888 name,
889 l->allow ? "Allow" : "Deny");
890 dump_acl_list(entry, l->aclList);
891 storeAppendPrintf(entry, "\n");
56b63fa1 892 }
30a4f2a8 893}
090089c4 894
8203a132 895static void
16300b58 896parse_acl_access(acl_access ** head)
090089c4 897{
a9f20260 898 aclParseAccessLine(LegacyParser, head);
090089c4 899}
900
0153d498 901static void
16300b58 902free_acl_access(acl_access ** head)
0153d498 903{
a47b9029 904 aclDestroyAccessList(head);
0153d498 905}
906
8203a132 907static void
62e76326 908
ddfcbc22 909dump_address(StoreEntry * entry, const char *name, struct IN_ADDR addr)
270b86af 910{
f53b06f9 911 storeAppendPrintf(entry, "%s %s\n", name, inet_ntoa(addr));
270b86af 912}
913
914static void
62e76326 915
ddfcbc22 916parse_address(struct IN_ADDR *addr)
090089c4 917{
62e76326 918
0ee4272b 919 const struct hostent *hp;
270b86af 920 char *token = strtok(NULL, w_space);
921
9eeb8e4b 922 if (!token) {
62e76326 923 self_destruct();
9eeb8e4b 924 return;
925 }
62e76326 926
429fdbec 927 if (safe_inet_addr(token, addr) == 1)
62e76326 928 (void) 0;
ceb8994e 929 else if ((hp = gethostbyname(token))) /* dont use ipcache */
62e76326 930 *addr = inaddrFromHostent(hp);
30a4f2a8 931 else
62e76326 932 self_destruct();
090089c4 933}
934
0153d498 935static void
62e76326 936
ddfcbc22 937free_address(struct IN_ADDR *addr)
0153d498 938{
62e76326 939
ddfcbc22 940 memset(addr, '\0', sizeof(struct IN_ADDR));
0153d498 941}
942
d6827718 943CBDATA_TYPE(acl_address);
944
945static void
946dump_acl_address(StoreEntry * entry, const char *name, acl_address * head)
947{
948 acl_address *l;
62e76326 949
d6827718 950 for (l = head; l; l = l->next) {
62e76326 951 if (l->addr.s_addr != INADDR_ANY)
952 storeAppendPrintf(entry, "%s %s", name, inet_ntoa(l->addr));
953 else
954 storeAppendPrintf(entry, "%s autoselect", name);
955
956 dump_acl_list(entry, l->aclList);
957
958 storeAppendPrintf(entry, "\n");
d6827718 959 }
960}
961
962static void
963freed_acl_address(void *data)
964{
e6ccf245 965 acl_address *l = static_cast<acl_address *>(data);
29b8d8d6 966 aclDestroyAclList(&l->aclList);
d6827718 967}
968
969static void
970parse_acl_address(acl_address ** head)
971{
972 acl_address *l;
973 acl_address **tail = head; /* sane name below */
974 CBDATA_INIT_TYPE_FREECB(acl_address, freed_acl_address);
975 l = cbdataAlloc(acl_address);
976 parse_address(&l->addr);
a9f20260 977 aclParseAclList(LegacyParser, &l->aclList);
62e76326 978
d6827718 979 while (*tail)
62e76326 980 tail = &(*tail)->next;
981
d6827718 982 *tail = l;
983}
984
985static void
986free_acl_address(acl_address ** head)
987{
988 while (*head) {
62e76326 989 acl_address *l = *head;
990 *head = l->next;
991 cbdataFree(l);
d6827718 992 }
993}
994
995CBDATA_TYPE(acl_tos);
996
997static void
998dump_acl_tos(StoreEntry * entry, const char *name, acl_tos * head)
999{
1000 acl_tos *l;
62e76326 1001
d6827718 1002 for (l = head; l; l = l->next) {
62e76326 1003 if (l->tos > 0)
1004 storeAppendPrintf(entry, "%s 0x%02X", name, l->tos);
1005 else
1006 storeAppendPrintf(entry, "%s none", name);
1007
1008 dump_acl_list(entry, l->aclList);
1009
1010 storeAppendPrintf(entry, "\n");
d6827718 1011 }
1012}
1013
1014static void
1015freed_acl_tos(void *data)
1016{
e6ccf245 1017 acl_tos *l = static_cast<acl_tos *>(data);
29b8d8d6 1018 aclDestroyAclList(&l->aclList);
d6827718 1019}
1020
1021static void
1022parse_acl_tos(acl_tos ** head)
1023{
1024 acl_tos *l;
1025 acl_tos **tail = head; /* sane name below */
1026 int tos;
1027 char junk;
1028 char *token = strtok(NULL, w_space);
62e76326 1029
9eeb8e4b 1030 if (!token) {
62e76326 1031 self_destruct();
9eeb8e4b 1032 return;
1033 }
62e76326 1034
9eeb8e4b 1035 if (sscanf(token, "0x%x%c", &tos, &junk) != 1) {
62e76326 1036 self_destruct();
9eeb8e4b 1037 return;
1038 }
62e76326 1039
9eeb8e4b 1040 if (tos < 0 || tos > 255) {
62e76326 1041 self_destruct();
9eeb8e4b 1042 return;
1043 }
62e76326 1044
d6827718 1045 CBDATA_INIT_TYPE_FREECB(acl_tos, freed_acl_tos);
62e76326 1046
d6827718 1047 l = cbdataAlloc(acl_tos);
62e76326 1048
d6827718 1049 l->tos = tos;
62e76326 1050
a9f20260 1051 aclParseAclList(LegacyParser, &l->aclList);
62e76326 1052
d6827718 1053 while (*tail)
62e76326 1054 tail = &(*tail)->next;
1055
d6827718 1056 *tail = l;
1057}
1058
1059static void
1060free_acl_tos(acl_tos ** head)
1061{
1062 while (*head) {
62e76326 1063 acl_tos *l = *head;
1064 *head = l->next;
1065 l->next = NULL;
1066 cbdataFree(l);
d6827718 1067 }
1068}
1069
ef1955a5 1070CBDATA_TYPE(acl_size_t);
1071
1072static void
1073dump_acl_b_size_t(StoreEntry * entry, const char *name, acl_size_t * head)
1074{
1075 acl_size_t *l;
1076
1077 for (l = head; l; l = l->next) {
ed013b6c 1078 if (l->size != -1)
ef1955a5 1079 storeAppendPrintf(entry, "%s %d %s\n", name, (int) l->size, B_BYTES_STR);
1080 else
1081 storeAppendPrintf(entry, "%s none", name);
1082
1083 dump_acl_list(entry, l->aclList);
1084
1085 storeAppendPrintf(entry, "\n");
1086 }
1087}
1088
1089static void
1090freed_acl_b_size_t(void *data)
1091{
1092 acl_size_t *l = static_cast<acl_size_t *>(data);
1093 aclDestroyAclList(&l->aclList);
1094}
1095
1096static void
1097parse_acl_b_size_t(acl_size_t ** head)
1098{
1099 acl_size_t *l;
1100 acl_size_t **tail = head; /* sane name below */
1101
1102 CBDATA_INIT_TYPE_FREECB(acl_size_t, freed_acl_b_size_t);
1103
1104 l = cbdataAlloc(acl_size_t);
1105
47f6e231 1106 parse_b_int64_t(&l->size);
ef1955a5 1107
a9f20260 1108 aclParseAclList(LegacyParser, &l->aclList);
ef1955a5 1109
1110 while (*tail)
1111 tail = &(*tail)->next;
1112
1113 *tail = l;
1114}
1115
1116static void
1117free_acl_b_size_t(acl_size_t ** head)
1118{
1119 while (*head) {
1120 acl_size_t *l = *head;
1121 *head = l->next;
1122 l->next = NULL;
1123 cbdataFree(l);
1124 }
1125}
1126
59715b38 1127#if DELAY_POOLS
1128
b67e2c8c 1129#include "DelayPools.h"
1130#include "DelayConfig.h"
59715b38 1131/* do nothing - free_delay_pool_count is the magic free function.
1132 * this is why delay_pool_count isn't just marked TYPE: ushort
1133 */
1134#define free_delay_pool_class(X)
1135#define free_delay_pool_access(X)
1136#define free_delay_pool_rates(X)
1137#define dump_delay_pool_class(X, Y, Z)
1138#define dump_delay_pool_access(X, Y, Z)
1139#define dump_delay_pool_rates(X, Y, Z)
1140
1141static void
b67e2c8c 1142free_delay_pool_count(DelayConfig * cfg)
59715b38 1143{
b67e2c8c 1144 cfg->freePoolCount();
59715b38 1145}
1146
1147static void
b67e2c8c 1148dump_delay_pool_count(StoreEntry * entry, const char *name, DelayConfig &cfg)
59715b38 1149{
b67e2c8c 1150 cfg.dumpPoolCount (entry, name);
59715b38 1151}
1152
1153static void
b67e2c8c 1154parse_delay_pool_count(DelayConfig * cfg)
59715b38 1155{
b67e2c8c 1156 cfg->parsePoolCount();
59715b38 1157}
1158
1159static void
b67e2c8c 1160parse_delay_pool_class(DelayConfig * cfg)
59715b38 1161{
b67e2c8c 1162 cfg->parsePoolClass();
59715b38 1163}
1164
1165static void
b67e2c8c 1166parse_delay_pool_rates(DelayConfig * cfg)
59715b38 1167{
b67e2c8c 1168 cfg->parsePoolRates();
59715b38 1169}
1170
1171static void
b67e2c8c 1172parse_delay_pool_access(DelayConfig * cfg)
59715b38 1173{
a9f20260 1174 cfg->parsePoolAccess(LegacyParser);
59715b38 1175}
62e76326 1176
59715b38 1177#endif
1178
c26ffae9 1179#if HTTP_VIOLATIONS
97474590 1180static void
6bccf575 1181dump_http_header_access(StoreEntry * entry, const char *name, header_mangler header[])
e3dd531e 1182{
efd900cb 1183 int i;
62e76326 1184
6bccf575 1185 for (i = 0; i < HDR_ENUM_END; i++) {
62e76326 1186 if (header[i].access_list != NULL) {
1187 storeAppendPrintf(entry, "%s ", name);
1188 dump_acl_access(entry, httpHeaderNameById(i),
1189 header[i].access_list);
1190 }
efd900cb 1191 }
97474590 1192}
e3dd531e 1193
97474590 1194static void
6bccf575 1195parse_http_header_access(header_mangler header[])
97474590 1196{
6bccf575 1197 int id, i;
97474590 1198 char *t = NULL;
62e76326 1199
97474590 1200 if ((t = strtok(NULL, w_space)) == NULL) {
bf8fe701 1201 debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
1202 debugs(3, 0, "parse_http_header_access: missing header name.");
62e76326 1203 return;
97474590 1204 }
62e76326 1205
6bccf575 1206 /* Now lookup index of header. */
1207 id = httpHeaderIdByNameDef(t, strlen(t));
62e76326 1208
6bccf575 1209 if (strcmp(t, "All") == 0)
62e76326 1210 id = HDR_ENUM_END;
6bccf575 1211 else if (strcmp(t, "Other") == 0)
62e76326 1212 id = HDR_OTHER;
6bccf575 1213 else if (id == -1) {
bf8fe701 1214 debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
1215 debugs(3, 0, "parse_http_header_access: unknown header name '" << t << "'");
62e76326 1216 return;
97474590 1217 }
62e76326 1218
6bccf575 1219 if (id != HDR_ENUM_END) {
62e76326 1220 parse_acl_access(&header[id].access_list);
6bccf575 1221 } else {
62e76326 1222 char *next_string = t + strlen(t) - 1;
1223 *next_string = 'A';
1224 *(next_string + 1) = ' ';
1225
1226 for (i = 0; i < HDR_ENUM_END; i++) {
1227 char *new_string = xstrdup(next_string);
1228 strtok(new_string, w_space);
1229 parse_acl_access(&header[i].access_list);
1230 safe_free(new_string);
1231 }
97474590 1232 }
6bccf575 1233}
1234
1235static void
1236free_http_header_access(header_mangler header[])
1237{
1238 int i;
62e76326 1239
6bccf575 1240 for (i = 0; i < HDR_ENUM_END; i++) {
62e76326 1241 free_acl_access(&header[i].access_list);
6bccf575 1242 }
1243}
1244
1245static void
1246dump_http_header_replace(StoreEntry * entry, const char *name, header_mangler
62e76326 1247 header[])
6bccf575 1248{
1249 int i;
62e76326 1250
6bccf575 1251 for (i = 0; i < HDR_ENUM_END; i++) {
62e76326 1252 if (NULL == header[i].replacement)
1253 continue;
1254
1255 storeAppendPrintf(entry, "%s %s %s\n", name, httpHeaderNameById(i),
1256 header[i].replacement);
97474590 1257 }
1258}
e3dd531e 1259
97474590 1260static void
6bccf575 1261parse_http_header_replace(header_mangler header[])
e3dd531e 1262{
6bccf575 1263 int id, i;
1264 char *t = NULL;
62e76326 1265
6bccf575 1266 if ((t = strtok(NULL, w_space)) == NULL) {
bf8fe701 1267 debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
1268 debugs(3, 0, "parse_http_header_replace: missing header name.");
62e76326 1269 return;
6bccf575 1270 }
62e76326 1271
6bccf575 1272 /* Now lookup index of header. */
1273 id = httpHeaderIdByNameDef(t, strlen(t));
62e76326 1274
6bccf575 1275 if (strcmp(t, "All") == 0)
62e76326 1276 id = HDR_ENUM_END;
6bccf575 1277 else if (strcmp(t, "Other") == 0)
62e76326 1278 id = HDR_OTHER;
6bccf575 1279 else if (id == -1) {
bf8fe701 1280 debugs(3, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
1281 debugs(3, 0, "parse_http_header_replace: unknown header name " << t << ".");
1282
62e76326 1283 return;
6bccf575 1284 }
62e76326 1285
6bccf575 1286 if (id != HDR_ENUM_END) {
62e76326 1287 if (header[id].replacement != NULL)
1288 safe_free(header[id].replacement);
1289
1290 header[id].replacement = xstrdup(t + strlen(t) + 1);
6bccf575 1291 } else {
62e76326 1292 for (i = 0; i < HDR_ENUM_END; i++) {
1293 if (header[i].replacement != NULL)
1294 safe_free(header[i].replacement);
1295
1296 header[i].replacement = xstrdup(t + strlen(t) + 1);
1297 }
6bccf575 1298 }
1299}
1300
1301static void
1302free_http_header_replace(header_mangler header[])
1303{
1304 int i;
62e76326 1305
6bccf575 1306 for (i = 0; i < HDR_ENUM_END; i++) {
62e76326 1307 if (header[i].replacement != NULL)
1308 safe_free(header[i].replacement);
6bccf575 1309 }
97474590 1310}
62e76326 1311
9e8b2f1c 1312#endif
97474590 1313
e90100aa 1314static void
e6ccf245 1315dump_cachedir(StoreEntry * entry, const char *name, _SquidConfig::_cacheSwap swap)
e90100aa 1316{
f53b06f9 1317 SwapDir *s;
1318 int i;
d3b3ab85 1319 assert (entry);
62e76326 1320
a7d59104 1321 for (i = 0; i < swap.n_configured; i++) {
c8f4eac4 1322 s = dynamic_cast<SwapDir *>(swap.swapDirs[i].getRaw());
d4e9f2ac 1323 if(!s) continue;
59b2d47f 1324 storeAppendPrintf(entry, "%s %s %s", name, s->type(), s->path);
62e76326 1325 s->dump(*entry);
62e76326 1326 storeAppendPrintf(entry, "\n");
f53b06f9 1327 }
1328}
1329
1330static int
e6ccf245 1331check_null_cachedir(_SquidConfig::_cacheSwap swap)
f53b06f9 1332{
1333 return swap.swapDirs == NULL;
e90100aa 1334}
1335
53ad48e6 1336static int
1337check_null_string(char *s)
1338{
1339 return s == NULL;
1340}
1341
94439e4e 1342static void
1343parse_authparam(authConfig * config)
1344{
1345 char *type_str;
1346 char *param_str;
94439e4e 1347
1348 if ((type_str = strtok(NULL, w_space)) == NULL)
62e76326 1349 self_destruct();
94439e4e 1350
1351 if ((param_str = strtok(NULL, w_space)) == NULL)
62e76326 1352 self_destruct();
94439e4e 1353
f5691f9c 1354 /* find a configuration for the scheme */
1355 AuthConfig *scheme = AuthConfig::Find (type_str);
62e76326 1356
f5691f9c 1357 if (scheme == NULL) {
1358 /* Create a configuration */
1359 AuthScheme *theScheme;
1360
1361 if ((theScheme = AuthScheme::Find(type_str)) == NULL) {
bf8fe701 1362 debugs(3, 0, "Parsing Config File: Unknown authentication scheme '" << type_str << "'.");
f5691f9c 1363 return;
62e76326 1364 }
94439e4e 1365
f5691f9c 1366 config->push_back(theScheme->createConfig());
1367 scheme = config->back();
1368 assert (scheme);
94439e4e 1369 }
62e76326 1370
f5691f9c 1371 scheme->parse(scheme, config->size(), param_str);
94439e4e 1372}
1373
1374static void
1375free_authparam(authConfig * cfg)
1376{
f5691f9c 1377 AuthConfig *scheme;
94439e4e 1378 /* DON'T FREE THESE FOR RECONFIGURE */
62e76326 1379
94439e4e 1380 if (reconfiguring)
62e76326 1381 return;
1382
f5691f9c 1383 while (cfg->size()) {
1384 scheme = cfg->pop_back();
1385 scheme->done();
94439e4e 1386 }
94439e4e 1387}
1388
1389static void
1390dump_authparam(StoreEntry * entry, const char *name, authConfig cfg)
1391{
f5691f9c 1392 for (authConfig::iterator i = cfg.begin(); i != cfg.end(); ++i)
1393 (*i)->dump(entry, name, (*i));
94439e4e 1394}
1395
59b2d47f 1396/* TODO: just return the object, the # is irrelevant */
cd748f27 1397static int
1398find_fstype(char *type)
1399{
59b2d47f 1400 for (size_t i = 0; i < StoreFileSystem::FileSystems().size(); ++i)
1401 if (strcasecmp(type, StoreFileSystem::FileSystems().items[i]->type()) == 0)
1402 return (int)i;
62e76326 1403
cd748f27 1404 return (-1);
1405}
1406
0e4e0e7d 1407static void
e6ccf245 1408parse_cachedir(_SquidConfig::_cacheSwap * swap)
0e4e0e7d 1409{
1410 char *type_str;
cd748f27 1411 char *path_str;
c8f4eac4 1412 RefCount<SwapDir> sd;
cd748f27 1413 int i;
1414 int fs;
cd748f27 1415
0e4e0e7d 1416 if ((type_str = strtok(NULL, w_space)) == NULL)
62e76326 1417 self_destruct();
cd748f27 1418
cd748f27 1419 if ((path_str = strtok(NULL, w_space)) == NULL)
62e76326 1420 self_destruct();
cd748f27 1421
c9e2e0e8 1422 fs = find_fstype(type_str);
1423
1424 if (fs < 0)
1425 self_destruct();
1426
1427 /* reconfigure existing dir */
cd748f27 1428
1429 for (i = 0; i < swap->n_configured; i++) {
c8f4eac4 1430 assert (swap->swapDirs[i].getRaw());
62e76326 1431
c9e2e0e8 1432 if ((strcasecmp(path_str, dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw())->path)
1433 ) == 0) {
1434 /* this is specific to on-fs Stores. The right
1435 * way to handle this is probably to have a mapping
1436 * from paths to stores, and have on-fs stores
1437 * register with that, and lookip in that in their
1438 * own setup logic. RBC 20041225. TODO.
1439 */
c8f4eac4 1440
1441 sd = dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw());
1442
c9e2e0e8 1443 if (sd->type() != StoreFileSystem::FileSystems().items[fs]->type()) {
bf8fe701 1444 debugs(3, 0, "ERROR: Can't change type of existing cache_dir " <<
1445 sd->type() << " " << sd->path << " to " << type_str << ". Restart required");
c9e2e0e8 1446 return;
1447 }
1448
62e76326 1449 sd->reconfigure (i, path_str);
c8f4eac4 1450
62e76326 1451 update_maxobjsize();
c8f4eac4 1452
62e76326 1453 return;
1454 }
cd748f27 1455 }
1456
c9e2e0e8 1457 /* new cache_dir */
2b6662ba 1458 assert(swap->n_configured < 63); /* 7 bits, signed */
dc986280 1459
cd748f27 1460 allocate_new_swapdir(swap);
c9e2e0e8 1461
59b2d47f 1462 swap->swapDirs[swap->n_configured] = StoreFileSystem::FileSystems().items[fs]->createSwapDir();
c9e2e0e8 1463
c8f4eac4 1464 sd = dynamic_cast<SwapDir *>(swap->swapDirs[swap->n_configured].getRaw());
c9e2e0e8 1465
8e8d4f30 1466 /* parse the FS parameters and options */
d3b3ab85 1467 sd->parse(swap->n_configured, path_str);
c9e2e0e8 1468
d3b3ab85 1469 ++swap->n_configured;
c9e2e0e8 1470
cd748f27 1471 /* Update the max object size */
1472 update_maxobjsize();
752c3b27 1473}
1474
2d72d4fd 1475static const char *
505e35db 1476peer_type_str(const peer_t type)
1477{
1f140227 1478 const char * result;
1479
0cdcddb9 1480 switch (type) {
62e76326 1481
505e35db 1482 case PEER_PARENT:
1f140227 1483 result = "parent";
62e76326 1484 break;
1485
505e35db 1486 case PEER_SIBLING:
1f140227 1487 result = "sibling";
62e76326 1488 break;
1489
505e35db 1490 case PEER_MULTICAST:
1f140227 1491 result = "multicast";
62e76326 1492 break;
1493
505e35db 1494 default:
1f140227 1495 result = "unknown";
62e76326 1496 break;
505e35db 1497 }
1f140227 1498
1499 return result;
505e35db 1500}
1501
f1dc9b30 1502static void
a7d59104 1503dump_peer(StoreEntry * entry, const char *name, peer * p)
98ffb7e4 1504{
505e35db 1505 domain_ping *d;
505e35db 1506 domain_type *t;
1507 LOCAL_ARRAY(char, xname, 128);
62e76326 1508
d41de3c1 1509 while (p != NULL) {
62e76326 1510 storeAppendPrintf(entry, "%s %s %s %d %d",
1511 name,
1512 p->host,
1513 neighborTypeStr(p),
1514 p->http_port,
1515 p->icp.port);
1516 dump_peer_options(entry, p);
1517
1518 for (d = p->peer_domain; d; d = d->next) {
1519 storeAppendPrintf(entry, "cache_peer_domain %s %s%s\n",
1520 p->host,
1521 d->do_ping ? null_string : "!",
1522 d->domain);
1523 }
1524
1525 if (p->access) {
1526 snprintf(xname, 128, "cache_peer_access %s", p->name);
1527 dump_acl_access(entry, xname, p->access);
1528 }
1529
1530 for (t = p->typelist; t; t = t->next) {
1531 storeAppendPrintf(entry, "neighbor_type_domain %s %s %s\n",
1532 p->host,
1533 peer_type_str(t->type),
1534 t->domain);
1535 }
1536
1537 p = p->next;
d41de3c1 1538 }
98ffb7e4 1539}
1540
609fac72 1541/**
1542 \param proto 'tcp' or 'udp' for protocol
1543 \returns Port the named service is supposed to be listening on.
1544 */
1545static u_short
1546GetService(const char *proto)
1547{
1548 struct servent *port = NULL;
1549 /** Parses a port number or service name from the squid.conf */
1550 char *token = strtok(NULL, w_space);
1551 if (token == NULL) {
1552 self_destruct();
4f6161dd 1553 return 0; /* NEVER REACHED */
609fac72 1554 }
1555 /** Returns either the service port number from /etc/services */
1556 port = getservbyname(token, proto);
1557 if (port != NULL) {
1558 return ntohs((u_short)port->s_port);
1559 }
1560 /** Or a numeric translation of the config text. */
1561 return xatos(token);
1562}
1563
1564/**
1565 \returns Port the named TCP service is supposed to be listening on.
1566 \copydoc GetService(const char *proto)
1567 */
1568inline u_short
1569GetTcpService(void)
1570{
1571 return GetService("tcp");
1572}
1573
1574/**
1575 \returns Port the named UDP service is supposed to be listening on.
1576 \copydoc GetService(const char *proto)
1577 */
1578inline u_short
1579GetUdpService(void)
1580{
1581 return GetService("udp");
1582}
1583
8203a132 1584static void
40a1495e 1585parse_peer(peer ** head)
7813c6d5 1586{
270b86af 1587 char *token = NULL;
40a1495e 1588 peer *p;
f5691f9c 1589 CBDATA_INIT_TYPE_FREECB(peer, peerDestroy);
72711e31 1590 p = cbdataAlloc(peer);
40a1495e 1591 p->http_port = CACHE_HTTP_PORT;
399cabec 1592 p->icp.port = CACHE_ICP_PORT;
40a1495e 1593 p->weight = 1;
d1b63fc8 1594 p->basetime = 0;
dc835977 1595 p->stats.logged_state = PEER_ALIVE;
62e76326 1596
e481c2dc 1597 if ((token = strtok(NULL, w_space)) == NULL)
62e76326 1598 self_destruct();
1599
40a1495e 1600 p->host = xstrdup(token);
62e76326 1601
be753325 1602 p->name = xstrdup(token);
62e76326 1603
e481c2dc 1604 if ((token = strtok(NULL, w_space)) == NULL)
62e76326 1605 self_destruct();
1606
40a1495e 1607 p->type = parseNeighborType(token);
62e76326 1608
0d5a2006 1609 if (p->type == PEER_MULTICAST) {
1610 p->options.no_digest = 1;
1611 p->options.no_netdb_exchange = 1;
1612 }
1613
609fac72 1614 p->http_port = GetTcpService();
62e76326 1615
0e656b69 1616 if (!p->http_port)
1617 self_destruct();
62e76326 1618
609fac72 1619 p->icp.port = GetUdpService();
62e76326 1620
270b86af 1621 while ((token = strtok(NULL, w_space))) {
62e76326 1622 if (!strcasecmp(token, "proxy-only")) {
1623 p->options.proxy_only = 1;
1624 } else if (!strcasecmp(token, "no-query")) {
1625 p->options.no_query = 1;
1626 } else if (!strcasecmp(token, "background-ping")) {
1627 p->options.background_ping = 1;
1628 } else if (!strcasecmp(token, "no-digest")) {
1629 p->options.no_digest = 1;
1630 } else if (!strcasecmp(token, "multicast-responder")) {
1631 p->options.mcast_responder = 1;
1632 } else if (!strncasecmp(token, "weight=", 7)) {
1633 p->weight = xatoi(token + 7);
1634 } else if (!strncasecmp(token, "basetime=", 9)) {
1635 p->basetime = xatoi(token + 9);
1636 } else if (!strcasecmp(token, "closest-only")) {
1637 p->options.closest_only = 1;
1638 } else if (!strncasecmp(token, "ttl=", 4)) {
1639 p->mcast.ttl = xatoi(token + 4);
1640
1641 if (p->mcast.ttl < 0)
1642 p->mcast.ttl = 0;
1643
1644 if (p->mcast.ttl > 128)
1645 p->mcast.ttl = 128;
1646 } else if (!strcasecmp(token, "default")) {
1647 p->options.default_parent = 1;
1648 } else if (!strcasecmp(token, "round-robin")) {
1649 p->options.roundrobin = 1;
1650 } else if (!strcasecmp(token, "weighted-round-robin")) {
1651 p->options.weighted_roundrobin = 1;
dc9d133b 1652#if USE_HTCP
62e76326 1653
1654 } else if (!strcasecmp(token, "htcp")) {
1655 p->options.htcp = 1;
527ee50d 1656 } else if (!strcasecmp(token, "htcp-oldsquid")) {
1657 p->options.htcp = 1;
1658 p->options.htcp_oldsquid = 1;
dc9d133b 1659#endif
62e76326 1660
1661 } else if (!strcasecmp(token, "no-netdb-exchange")) {
1662 p->options.no_netdb_exchange = 1;
afd88fbe 1663#if USE_CARP
62e76326 1664
1665 } else if (!strcasecmp(token, "carp")) {
1666 if (p->type != PEER_PARENT)
1667 fatalf("parse_peer: non-parent carp peer %s/%d\n", p->host, p->http_port);
1668
1669 p->options.carp = 1;
1670
95e36d02 1671#endif
1672#if DELAY_POOLS
62e76326 1673
1674 } else if (!strcasecmp(token, "no-delay")) {
1675 p->options.no_delay = 1;
afd88fbe 1676#endif
62e76326 1677
1678 } else if (!strncasecmp(token, "login=", 6)) {
1679 p->login = xstrdup(token + 6);
1680 rfc1738_unescape(p->login);
1681 } else if (!strncasecmp(token, "connect-timeout=", 16)) {
1682 p->connect_timeout = xatoi(token + 16);
7e3ce7b9 1683#if USE_CACHE_DIGESTS
62e76326 1684
1685 } else if (!strncasecmp(token, "digest-url=", 11)) {
1686 p->digest_url = xstrdup(token + 11);
7e3ce7b9 1687#endif
62e76326 1688
1689 } else if (!strcasecmp(token, "allow-miss")) {
1690 p->options.allow_miss = 1;
1691 } else if (!strncasecmp(token, "max-conn=", 9)) {
1692 p->max_conn = xatoi(token + 9);
1693 } else if (!strcasecmp(token, "originserver")) {
1694 p->options.originserver = 1;
1695 } else if (!strncasecmp(token, "name=", 5)) {
1696 safe_free(p->name);
1697
1698 if (token[5])
1699 p->name = xstrdup(token + 5);
1700 } else if (!strncasecmp(token, "forceddomain=", 13)) {
1701 safe_free(p->domain);
1702
1703 if (token[13])
1704 p->domain = xstrdup(token + 13);
1705
a7ad6e4e 1706#if USE_SSL
62e76326 1707
1708 } else if (strcmp(token, "ssl") == 0) {
1709 p->use_ssl = 1;
1710 } else if (strncmp(token, "sslcert=", 8) == 0) {
1711 safe_free(p->sslcert);
1712 p->sslcert = xstrdup(token + 8);
1713 } else if (strncmp(token, "sslkey=", 7) == 0) {
1714 safe_free(p->sslkey);
1715 p->sslkey = xstrdup(token + 7);
1716 } else if (strncmp(token, "sslversion=", 11) == 0) {
1717 p->sslversion = atoi(token + 11);
1718 } else if (strncmp(token, "ssloptions=", 11) == 0) {
1719 safe_free(p->ssloptions);
1720 p->ssloptions = xstrdup(token + 11);
1721 } else if (strncmp(token, "sslcipher=", 10) == 0) {
1722 safe_free(p->sslcipher);
1723 p->sslcipher = xstrdup(token + 10);
1724 } else if (strncmp(token, "sslcafile=", 10) == 0) {
1725 safe_free(p->sslcafile);
a82a4fe4 1726 p->sslcafile = xstrdup(token + 10);
62e76326 1727 } else if (strncmp(token, "sslcapath=", 10) == 0) {
1728 safe_free(p->sslcapath);
a82a4fe4 1729 p->sslcapath = xstrdup(token + 10);
1730 } else if (strncmp(token, "sslcrlfile=", 11) == 0) {
1731 safe_free(p->sslcrlfile);
1732 p->sslcapath = xstrdup(token + 10);
62e76326 1733 } else if (strncmp(token, "sslflags=", 9) == 0) {
1734 safe_free(p->sslflags);
1735 p->sslflags = xstrdup(token + 9);
1736 } else if (strncmp(token, "ssldomain=", 10) == 0) {
1737 safe_free(p->ssldomain);
1738 p->ssldomain = xstrdup(token + 10);
a7ad6e4e 1739#endif
62e76326 1740
1741 } else if (strcmp(token, "front-end-https") == 0) {
1742 p->front_end_https = 1;
1743 } else if (strcmp(token, "front-end-https=on") == 0) {
1744 p->front_end_https = 1;
1745 } else if (strcmp(token, "front-end-https=auto") == 0) {
1746 p->front_end_https = 2;
1747 } else {
bf8fe701 1748 debugs(3, 0, "parse_peer: token='" << token << "'");
62e76326 1749 self_destruct();
1750 }
270b86af 1751 }
62e76326 1752
be753325 1753 if (peerFindByName(p->name))
62e76326 1754 fatalf("ERROR: cache_peer %s specified twice\n", p->name);
1755
40a1495e 1756 if (p->weight < 1)
62e76326 1757 p->weight = 1;
1758
399cabec 1759 p->icp.version = ICP_VERSION_CURRENT;
62e76326 1760
eb406bb7 1761 p->test_fd = -1;
62e76326 1762
e13ee7ad 1763#if USE_CACHE_DIGESTS
62e76326 1764
e13ee7ad 1765 if (!p->options.no_digest) {
62e76326 1766 /* XXX This looks odd.. who has the original pointer
1767 * then?
1768 */
1769 PeerDigest *pd = peerDigestCreate(p);
1770 p->digest = cbdataReference(pd);
8a6218c6 1771 }
62e76326 1772
e13ee7ad 1773#endif
0153d498 1774 while (*head != NULL)
62e76326 1775 head = &(*head)->next;
1776
0153d498 1777 *head = p;
62e76326 1778
40a1495e 1779 Config.npeers++;
62e76326 1780
82056f1e 1781 peerClearRR(p);
0153d498 1782}
1783
1784static void
40a1495e 1785free_peer(peer ** P)
0153d498 1786{
40a1495e 1787 peer *p;
62e76326 1788
79d39a72 1789 while ((p = *P) != NULL) {
62e76326 1790 *P = p->next;
3855c318 1791#if USE_CACHE_DIGESTS
62e76326 1792
1793 cbdataReferenceDone(p->digest);
3855c318 1794#endif
62e76326 1795
1796 cbdataFree(p);
a47b9029 1797 }
62e76326 1798
987c67d1 1799 Config.npeers = 0;
270b86af 1800}
1801
1802static void
a7d59104 1803dump_cachemgrpasswd(StoreEntry * entry, const char *name, cachemgr_passwd * list)
270b86af 1804{
d41de3c1 1805 wordlist *w;
62e76326 1806
d41de3c1 1807 while (list != NULL) {
62e76326 1808 if (strcmp(list->passwd, "none") && strcmp(list->passwd, "disable"))
1809 storeAppendPrintf(entry, "%s XXXXXXXXXX", name);
1810 else
1811 storeAppendPrintf(entry, "%s %s", name, list->passwd);
1812
1813 for (w = list->actions; w != NULL; w = w->next) {
1814 storeAppendPrintf(entry, " %s", w->key);
1815 }
1816
1817 storeAppendPrintf(entry, "\n");
1818 list = list->next;
d41de3c1 1819 }
270b86af 1820}
1821
1822static void
a47b9029 1823parse_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 1824{
1825 char *passwd = NULL;
1826 wordlist *actions = NULL;
22f3fd98 1827 cachemgr_passwd *p;
1828 cachemgr_passwd **P;
270b86af 1829 parse_string(&passwd);
1830 parse_wordlist(&actions);
e6ccf245 1831 p = static_cast<cachemgr_passwd *>(xcalloc(1, sizeof(cachemgr_passwd)));
22f3fd98 1832 p->passwd = passwd;
1833 p->actions = actions;
62e76326 1834
26aa7e31 1835 for (P = head; *P; P = &(*P)->next) {
62e76326 1836 /*
1837 * See if any of the actions from this line already have a
1838 * password from previous lines. The password checking
1839 * routines in cache_manager.c take the the password from
1840 * the first cachemgr_passwd struct that contains the
1841 * requested action. Thus, we should warn users who might
1842 * think they can have two passwords for the same action.
1843 */
1844 wordlist *w;
1845 wordlist *u;
1846
1847 for (w = (*P)->actions; w; w = w->next) {
1848 for (u = actions; u; u = u->next) {
1849 if (strcmp(w->key, u->key))
1850 continue;
1851
bf8fe701 1852 debugs(0, 0, "WARNING: action '" << u->key << "' (line " << config_lineno << ") already has a password");
62e76326 1853 }
1854 }
26aa7e31 1855 }
62e76326 1856
22f3fd98 1857 *P = p;
270b86af 1858}
1859
1860static void
a47b9029 1861free_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 1862{
a47b9029 1863 cachemgr_passwd *p;
62e76326 1864
79d39a72 1865 while ((p = *head) != NULL) {
62e76326 1866 *head = p->next;
1867 xfree(p->passwd);
1868 wordlistDestroy(&p->actions);
1869 xfree(p);
a47b9029 1870 }
270b86af 1871}
1872
8203a132 1873static void
16300b58 1874dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var)
270b86af 1875{
d41de3c1 1876 acl_name_list *a;
62e76326 1877
d41de3c1 1878 while (var != NULL) {
62e76326 1879 storeAppendPrintf(entry, "%s %s", name, var->err_page_name);
1880
1881 for (a = var->acl_list; a != NULL; a = a->next)
1882 storeAppendPrintf(entry, " %s", a->name);
1883
1884 storeAppendPrintf(entry, "\n");
1885
1886 var = var->next;
d41de3c1 1887 }
270b86af 1888}
1889
1890static void
16300b58 1891parse_denyinfo(acl_deny_info_list ** var)
6e40f263 1892{
f1dc9b30 1893 aclParseDenyInfoLine(var);
6e40f263 1894}
403279e0 1895
1273d501 1896void
a47b9029 1897free_denyinfo(acl_deny_info_list ** list)
3c5557f9 1898{
56b63fa1 1899 acl_deny_info_list *a = NULL;
1900 acl_deny_info_list *a_next = NULL;
1901 acl_name_list *l = NULL;
1902 acl_name_list *l_next = NULL;
62e76326 1903
1273d501 1904 for (a = *list; a; a = a_next) {
62e76326 1905 for (l = a->acl_list; l; l = l_next) {
1906 l_next = l->next;
1907 memFree(l, MEM_ACL_NAME_LIST);
1908 l = NULL;
1909 }
1910
1911 a_next = a->next;
1912 memFree(a, MEM_ACL_DENY_INFO_LIST);
1913 a = NULL;
1273d501 1914 }
62e76326 1915
1273d501 1916 *list = NULL;
270b86af 1917}
1918
1919static void
505e35db 1920parse_peer_access(void)
270b86af 1921{
1922 char *host = NULL;
505e35db 1923 peer *p;
62e76326 1924
270b86af 1925 if (!(host = strtok(NULL, w_space)))
62e76326 1926 self_destruct();
1927
0cdcddb9 1928 if ((p = peerFindByName(host)) == NULL) {
bf8fe701 1929 debugs(15, 0, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
62e76326 1930 return;
0cdcddb9 1931 }
62e76326 1932
a9f20260 1933 aclParseAccessLine(LegacyParser, &p->access);
270b86af 1934}
1935
270b86af 1936static void
1937parse_hostdomain(void)
1938{
1939 char *host = NULL;
1940 char *domain = NULL;
62e76326 1941
270b86af 1942 if (!(host = strtok(NULL, w_space)))
62e76326 1943 self_destruct();
1944
f1dc9b30 1945 while ((domain = strtok(NULL, list_sep))) {
62e76326 1946 domain_ping *l = NULL;
1947 domain_ping **L = NULL;
1948 peer *p;
1949
1950 if ((p = peerFindByName(host)) == NULL) {
bf8fe701 1951 debugs(15, 0, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
62e76326 1952 continue;
1953 }
1954
1955 l = static_cast<domain_ping *>(xcalloc(1, sizeof(domain_ping)));
1956 l->do_ping = 1;
1957
1958 if (*domain == '!') { /* check for !.edu */
1959 l->do_ping = 0;
1960 domain++;
1961 }
1962
1963 l->domain = xstrdup(domain);
1964
1965 for (L = &(p->peer_domain); *L; L = &((*L)->next))
1966
1967 ;
1968 *L = l;
f1dc9b30 1969 }
270b86af 1970}
1971
1972static void
1973parse_hostdomaintype(void)
1974{
1975 char *host = NULL;
1976 char *type = NULL;
1977 char *domain = NULL;
62e76326 1978
270b86af 1979 if (!(host = strtok(NULL, w_space)))
62e76326 1980 self_destruct();
1981
270b86af 1982 if (!(type = strtok(NULL, w_space)))
62e76326 1983 self_destruct();
1984
f1dc9b30 1985 while ((domain = strtok(NULL, list_sep))) {
62e76326 1986 domain_type *l = NULL;
1987 domain_type **L = NULL;
1988 peer *p;
1989
1990 if ((p = peerFindByName(host)) == NULL) {
bf8fe701 1991 debugs(15, 0, "" << cfg_filename << ", line " << config_lineno << ": No cache_peer '" << host << "'");
62e76326 1992 return;
1993 }
1994
1995 l = static_cast<domain_type *>(xcalloc(1, sizeof(domain_type)));
1996 l->type = parseNeighborType(type);
1997 l->domain = xstrdup(domain);
1998
1999 for (L = &(p->typelist); *L; L = &((*L)->next))
2000
2001 ;
2002 *L = l;
f1dc9b30 2003 }
270b86af 2004}
2005
270b86af 2006static void
a7d59104 2007dump_int(StoreEntry * entry, const char *name, int var)
270b86af 2008{
f53b06f9 2009 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 2010}
c1c29eb6 2011
94439e4e 2012void
270b86af 2013parse_int(int *var)
2014{
270b86af 2015 int i;
0e4e0e7d 2016 i = GetInteger();
270b86af 2017 *var = i;
2018}
090089c4 2019
0153d498 2020static void
2021free_int(int *var)
2022{
a47b9029 2023 *var = 0;
0153d498 2024}
2025
270b86af 2026static void
a7d59104 2027dump_onoff(StoreEntry * entry, const char *name, int var)
270b86af 2028{
f53b06f9 2029 storeAppendPrintf(entry, "%s %s\n", name, var ? "on" : "off");
270b86af 2030}
090089c4 2031
d205783b 2032void
270b86af 2033parse_onoff(int *var)
2034{
2035 char *token = strtok(NULL, w_space);
090089c4 2036
270b86af 2037 if (token == NULL)
62e76326 2038 self_destruct();
2039
270b86af 2040 if (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))
62e76326 2041 *var = 1;
270b86af 2042 else
62e76326 2043 *var = 0;
270b86af 2044}
e90100aa 2045
0153d498 2046#define free_onoff free_int
52d3f198 2047
2048static void
2049dump_tristate(StoreEntry * entry, const char *name, int var)
2050{
2051 const char *state;
2052
2053 if (var > 0)
2054 state = "on";
2055 else if (var < 0)
2056 state = "warn";
2057 else
2058 state = "off";
2059
2060 storeAppendPrintf(entry, "%s %s\n", name, state);
2061}
2062
2063static void
2064parse_tristate(int *var)
2065{
2066 char *token = strtok(NULL, w_space);
2067
2068 if (token == NULL)
2069 self_destruct();
2070
2071 if (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))
2072 *var = 1;
2073 else if (!strcasecmp(token, "warn"))
2074 *var = -1;
2075 else
2076 *var = 0;
2077}
2078
2079#define free_tristate free_int
30a4f2a8 2080
270b86af 2081static void
a7d59104 2082dump_refreshpattern(StoreEntry * entry, const char *name, refresh_t * head)
270b86af 2083{
d41de3c1 2084 while (head != NULL) {
62e76326 2085 storeAppendPrintf(entry, "%s%s %s %d %d%% %d\n",
2086 name,
2087 head->flags.icase ? " -i" : null_string,
2088 head->pattern,
2089 (int) head->min / 60,
2090 (int) (100.0 * head->pct + 0.5),
2091 (int) head->max / 60);
4c3ef9b2 2092
2093 if (head->flags.refresh_ims)
2094 storeAppendPrintf(entry, " refresh-ims");
2095
9f60cfdf 2096#if HTTP_VIOLATIONS
62e76326 2097
2098 if (head->flags.override_expire)
2099 storeAppendPrintf(entry, " override-expire");
2100
2101 if (head->flags.override_lastmod)
2102 storeAppendPrintf(entry, " override-lastmod");
2103
2104 if (head->flags.reload_into_ims)
2105 storeAppendPrintf(entry, " reload-into-ims");
2106
2107 if (head->flags.ignore_reload)
2108 storeAppendPrintf(entry, " ignore-reload");
2109
38f9c547 2110 if (head->flags.ignore_no_cache)
2111 storeAppendPrintf(entry, " ignore-no-cache");
2112
2113 if (head->flags.ignore_no_store)
2114 storeAppendPrintf(entry, " ignore-no-store");
2115
2116 if (head->flags.ignore_private)
2117 storeAppendPrintf(entry, " ignore-private");
2118
2119 if (head->flags.ignore_auth)
2120 storeAppendPrintf(entry, " ignore-auth");
2121
9f60cfdf 2122#endif
62e76326 2123
2124 storeAppendPrintf(entry, "\n");
2125
2126 head = head->next;
d41de3c1 2127 }
270b86af 2128}
090089c4 2129
270b86af 2130static void
f1dc9b30 2131parse_refreshpattern(refresh_t ** head)
270b86af 2132{
f1dc9b30 2133 char *token;
2134 char *pattern;
2135 time_t min = 0;
c3f6d204 2136 double pct = 0.0;
f1dc9b30 2137 time_t max = 0;
4c3ef9b2 2138 int refresh_ims = 0;
9f60cfdf 2139#if HTTP_VIOLATIONS
62e76326 2140
1dfa1d81 2141 int override_expire = 0;
2142 int override_lastmod = 0;
cbe3a719 2143 int reload_into_ims = 0;
2144 int ignore_reload = 0;
38f9c547 2145 int ignore_no_cache = 0;
2146 int ignore_no_store = 0;
2147 int ignore_private = 0;
2148 int ignore_auth = 0;
9f60cfdf 2149#endif
62e76326 2150
f1dc9b30 2151 int i;
2152 refresh_t *t;
2153 regex_t comp;
2154 int errcode;
2155 int flags = REG_EXTENDED | REG_NOSUB;
62e76326 2156
9eeb8e4b 2157 if ((token = strtok(NULL, w_space)) == NULL) {
62e76326 2158 self_destruct();
9eeb8e4b 2159 return;
2160 }
62e76326 2161
f1dc9b30 2162 if (strcmp(token, "-i") == 0) {
62e76326 2163 flags |= REG_ICASE;
2164 token = strtok(NULL, w_space);
f1dc9b30 2165 } else if (strcmp(token, "+i") == 0) {
62e76326 2166 flags &= ~REG_ICASE;
2167 token = strtok(NULL, w_space);
f1dc9b30 2168 }
62e76326 2169
9eeb8e4b 2170 if (token == NULL) {
62e76326 2171 self_destruct();
9eeb8e4b 2172 return;
2173 }
62e76326 2174
f1dc9b30 2175 pattern = xstrdup(token);
62e76326 2176
0e4e0e7d 2177 i = GetInteger(); /* token: min */
62e76326 2178
f1dc9b30 2179 min = (time_t) (i * 60); /* convert minutes to seconds */
62e76326 2180
0e4e0e7d 2181 i = GetInteger(); /* token: pct */
62e76326 2182
c3f6d204 2183 pct = (double) i / 100.0;
62e76326 2184
0e4e0e7d 2185 i = GetInteger(); /* token: max */
62e76326 2186
f1dc9b30 2187 max = (time_t) (i * 60); /* convert minutes to seconds */
62e76326 2188
1dfa1d81 2189 /* Options */
2190 while ((token = strtok(NULL, w_space)) != NULL) {
4c3ef9b2 2191 if (!strcmp(token, "refresh-ims")) {
2192 refresh_ims = 1;
9f60cfdf 2193#if HTTP_VIOLATIONS
62e76326 2194
4c3ef9b2 2195 } else if (!strcmp(token, "override-expire"))
62e76326 2196 override_expire = 1;
2197 else if (!strcmp(token, "override-lastmod"))
2198 override_lastmod = 1;
38f9c547 2199 else if (!strcmp(token, "ignore-no-cache"))
2200 ignore_no_cache = 1;
2201 else if (!strcmp(token, "ignore-no-store"))
2202 ignore_no_store = 1;
2203 else if (!strcmp(token, "ignore-private"))
2204 ignore_private = 1;
2205 else if (!strcmp(token, "ignore-auth"))
2206 ignore_auth = 1;
62e76326 2207 else if (!strcmp(token, "reload-into-ims")) {
2208 reload_into_ims = 1;
2209 refresh_nocache_hack = 1;
2210 /* tell client_side.c that this is used */
2211 } else if (!strcmp(token, "ignore-reload")) {
2212 ignore_reload = 1;
2213 refresh_nocache_hack = 1;
2214 /* tell client_side.c that this is used */
9f60cfdf 2215#endif
62e76326 2216
4c3ef9b2 2217 } else
bf8fe701 2218 debugs(22, 0, "redreshAddToList: Unknown option '" << pattern << "': " << token);
1dfa1d81 2219 }
62e76326 2220
f1dc9b30 2221 if ((errcode = regcomp(&comp, pattern, flags)) != 0) {
62e76326 2222 char errbuf[256];
2223 regerror(errcode, &comp, errbuf, sizeof errbuf);
bf8fe701 2224 debugs(22, 0, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
2225 debugs(22, 0, "refreshAddToList: Invalid regular expression '" << pattern << "': " << errbuf);
62e76326 2226 return;
f1dc9b30 2227 }
62e76326 2228
c3f6d204 2229 pct = pct < 0.0 ? 0.0 : pct;
f1dc9b30 2230 max = max < 0 ? 0 : max;
e6ccf245 2231 t = static_cast<refresh_t *>(xcalloc(1, sizeof(refresh_t)));
f1dc9b30 2232 t->pattern = (char *) xstrdup(pattern);
2233 t->compiled_pattern = comp;
2234 t->min = min;
c3f6d204 2235 t->pct = pct;
f1dc9b30 2236 t->max = max;
62e76326 2237
c3f6d204 2238 if (flags & REG_ICASE)
62e76326 2239 t->flags.icase = 1;
2240
4c3ef9b2 2241 if (refresh_ims)
2242 t->flags.refresh_ims = 1;
2243
9f60cfdf 2244#if HTTP_VIOLATIONS
62e76326 2245
1dfa1d81 2246 if (override_expire)
62e76326 2247 t->flags.override_expire = 1;
2248
1dfa1d81 2249 if (override_lastmod)
62e76326 2250 t->flags.override_lastmod = 1;
2251
cbe3a719 2252 if (reload_into_ims)
62e76326 2253 t->flags.reload_into_ims = 1;
2254
cbe3a719 2255 if (ignore_reload)
62e76326 2256 t->flags.ignore_reload = 1;
2257
38f9c547 2258 if (ignore_no_cache)
2259 t->flags.ignore_no_cache = 1;
2260
2261 if (ignore_no_store)
2262 t->flags.ignore_no_store = 1;
2263
2264 if (ignore_private)
2265 t->flags.ignore_private = 1;
2266
2267 if (ignore_auth)
2268 t->flags.ignore_auth = 1;
2269
9f60cfdf 2270#endif
62e76326 2271
f1dc9b30 2272 t->next = NULL;
62e76326 2273
f1dc9b30 2274 while (*head)
62e76326 2275 head = &(*head)->next;
2276
f1dc9b30 2277 *head = t;
62e76326 2278
f1dc9b30 2279 safe_free(pattern);
270b86af 2280}
090089c4 2281
270b86af 2282static void
a47b9029 2283free_refreshpattern(refresh_t ** head)
270b86af 2284{
f1dc9b30 2285 refresh_t *t;
62e76326 2286
79d39a72 2287 while ((t = *head) != NULL) {
62e76326 2288 *head = t->next;
2289 safe_free(t->pattern);
2290 regfree(&t->compiled_pattern);
2291 safe_free(t);
f1dc9b30 2292 }
c2066637 2293
8970d351 2294#if HTTP_VIOLATIONS
c2066637 2295 refresh_nocache_hack = 0;
8970d351 2296
2297#endif
270b86af 2298}
12b9e9b1 2299
270b86af 2300static void
a7d59104 2301dump_string(StoreEntry * entry, const char *name, char *var)
270b86af 2302{
f53b06f9 2303 if (var != NULL)
62e76326 2304 storeAppendPrintf(entry, "%s %s\n", name, var);
270b86af 2305}
98ffb7e4 2306
270b86af 2307static void
0153d498 2308parse_string(char **var)
270b86af 2309{
2310 char *token = strtok(NULL, w_space);
270b86af 2311 safe_free(*var);
62e76326 2312
270b86af 2313 if (token == NULL)
62e76326 2314 self_destruct();
2315
270b86af 2316 *var = xstrdup(token);
2317}
b15e6857 2318
3a69ddf3 2319void
2320ConfigParser::ParseString(char **var)
2321{
2322 parse_string(var);
2323}
2324
2325void
30abd221 2326ConfigParser::ParseString(String *var)
3a69ddf3 2327{
2328 char *token = strtok(NULL, w_space);
2329
2330 if (token == NULL)
2331 self_destruct();
2332
30abd221 2333 var->reset(token);
3a69ddf3 2334}
2335
0153d498 2336static void
2337free_string(char **var)
2338{
027acbaf 2339 safe_free(*var);
0153d498 2340}
caebbe00 2341
94439e4e 2342void
f1dc9b30 2343parse_eol(char *volatile *var)
270b86af 2344{
852751f7 2345 unsigned char *token = (unsigned char *) strtok(NULL, null_string);
270b86af 2346 safe_free(*var);
62e76326 2347
9eeb8e4b 2348 if (!token) {
62e76326 2349 self_destruct();
9eeb8e4b 2350 return;
2351 }
62e76326 2352
e4755e29 2353 while (*token && xisspace(*token))
62e76326 2354 token++;
2355
9eeb8e4b 2356 if (!*token) {
62e76326 2357 self_destruct();
9eeb8e4b 2358 return;
2359 }
62e76326 2360
852751f7 2361 *var = xstrdup((char *) token);
270b86af 2362}
090089c4 2363
52d3f198 2364#define dump_eol dump_string
2365#define free_eol free_string
2366
d9e04dc7 2367void
2368parse_debug(char *volatile *var)
2369{
2370 parse_eol(var);
2371 safe_free(debug_options)
2372 debug_options = xstrdup(Config.debugOptions);
2373 Debug::parseOptions(Config.debugOptions);
2374}
2375
52d3f198 2376#define dump_debug dump_string
2377#define free_debug free_string
2378
270b86af 2379static void
a7d59104 2380dump_time_t(StoreEntry * entry, const char *name, time_t var)
090089c4 2381{
f53b06f9 2382 storeAppendPrintf(entry, "%s %d seconds\n", name, (int) var);
090089c4 2383}
2384
94439e4e 2385void
a47b9029 2386parse_time_t(time_t * var)
0ffd22bc 2387{
f1dc9b30 2388 parseTimeLine(var, T_SECOND_STR);
0ffd22bc 2389}
2390
270b86af 2391static void
a47b9029 2392free_time_t(time_t * var)
270b86af 2393{
a47b9029 2394 *var = 0;
270b86af 2395}
9906e724 2396
2397static void
a7d59104 2398dump_size_t(StoreEntry * entry, const char *name, size_t var)
1b635117 2399{
f53b06f9 2400 storeAppendPrintf(entry, "%s %d\n", name, (int) var);
1b635117 2401}
2402
2403static void
a7d59104 2404dump_b_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 2405{
f53b06f9 2406 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
9906e724 2407}
2408
3e62bd58 2409#if UNUSED_CODE
9906e724 2410static void
a7d59104 2411dump_kb_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 2412{
f53b06f9 2413 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_KBYTES_STR);
9906e724 2414}
3e62bd58 2415#endif
9906e724 2416
47f6e231 2417static void
2418dump_b_int64_t(StoreEntry * entry, const char *name, int64_t var)
2419{
2420 storeAppendPrintf(entry, "%s %"PRId64" %s\n", name, var, B_BYTES_STR);
2421}
2422
2423static void
2424dump_kb_int64_t(StoreEntry * entry, const char *name, int64_t var)
2425{
2426 storeAppendPrintf(entry, "%s %"PRId64" %s\n", name, var, B_KBYTES_STR);
2427}
2428
9906e724 2429static void
a47b9029 2430parse_size_t(size_t * var)
1b635117 2431{
1b635117 2432 int i;
0e4e0e7d 2433 i = GetInteger();
1b635117 2434 *var = (size_t) i;
2435}
2436
2437static void
2438parse_b_size_t(size_t * var)
9906e724 2439{
2440 parseBytesLine(var, B_BYTES_STR);
2441}
2442
3e62bd58 2443#if UNUSED_CODE
9906e724 2444static void
a47b9029 2445parse_kb_size_t(size_t * var)
9906e724 2446{
2447 parseBytesLine(var, B_KBYTES_STR);
2448}
3e62bd58 2449#endif
9906e724 2450
47f6e231 2451static void
2452parse_b_int64_t(int64_t * var)
2453{
2454 parseBytesLine64(var, B_BYTES_STR);
2455}
2456
2457static void
2458parse_kb_int64_t(int64_t * var)
2459{
2460 parseBytesLine64(var, B_KBYTES_STR);
2461}
2462
9906e724 2463static void
a47b9029 2464free_size_t(size_t * var)
9906e724 2465{
a47b9029 2466 *var = 0;
9906e724 2467}
2468
47f6e231 2469static void
2470free_b_int64_t(int64_t * var)
2471{
2472 *var = 0;
2473}
2474
1b635117 2475#define free_b_size_t free_size_t
9906e724 2476#define free_kb_size_t free_size_t
2477#define free_mb_size_t free_size_t
2478#define free_gb_size_t free_size_t
47f6e231 2479#define free_kb_int64_t free_b_int64_t
090089c4 2480
8203a132 2481static void
a7d59104 2482dump_ushort(StoreEntry * entry, const char *name, u_short var)
090089c4 2483{
f53b06f9 2484 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 2485}
090089c4 2486
0153d498 2487static void
a47b9029 2488free_ushort(u_short * u)
0153d498 2489{
2490 *u = 0;
2491}
2492
270b86af 2493static void
2494parse_ushort(u_short * var)
b67e2c8c 2495{
2496 ConfigParser::ParseUShort(var);
2497}
2498
2499void
2500ConfigParser::ParseUShort(u_short *var)
270b86af 2501{
0e656b69 2502 *var = GetShort();
090089c4 2503}
2504
3a69ddf3 2505void
2506ConfigParser::ParseBool(bool *var)
2507{
2508 int i = GetInteger();
2509
2510 if (0 == i)
2511 *var = false;
2512 else if (1 == i)
2513 *var = true;
2514 else
2515 self_destruct();
2516}
2517
270b86af 2518static void
a7d59104 2519dump_wordlist(StoreEntry * entry, const char *name, wordlist * list)
270b86af 2520{
270b86af 2521 while (list != NULL) {
62e76326 2522 storeAppendPrintf(entry, "%s %s\n", name, list->key);
2523 list = list->next;
429fdbec 2524 }
429fdbec 2525}
2526
3a69ddf3 2527void
2528ConfigParser::ParseWordList(wordlist ** list)
2529{
2530 parse_wordlist(list);
2531}
2532
94439e4e 2533void
270b86af 2534parse_wordlist(wordlist ** list)
429fdbec 2535{
270b86af 2536 char *token;
a3c6890f 2537 char *t = strtok(NULL, "");
62e76326 2538
a3c6890f 2539 while ((token = strwordtok(NULL, &t)))
62e76326 2540 wordlistAdd(list, token);
429fdbec 2541}
270b86af 2542
f8d9f54a 2543static int
5da06f20 2544check_null_wordlist(wordlist * w)
f8d9f54a 2545{
2546 return w == NULL;
2547}
2548
63e9d884 2549static int
c6d5b87b 2550check_null_acl_access(acl_access * a)
63e9d884 2551{
2552 return a == NULL;
2553}
2554
0153d498 2555#define free_wordlist wordlistDestroy
270b86af 2556
d548ee64 2557#define free_uri_whitespace free_int
2558
2559static void
2560parse_uri_whitespace(int *var)
2561{
2562 char *token = strtok(NULL, w_space);
62e76326 2563
d548ee64 2564 if (token == NULL)
62e76326 2565 self_destruct();
2566
7e3ce7b9 2567 if (!strcasecmp(token, "strip"))
62e76326 2568 *var = URI_WHITESPACE_STRIP;
7e3ce7b9 2569 else if (!strcasecmp(token, "deny"))
62e76326 2570 *var = URI_WHITESPACE_DENY;
d548ee64 2571 else if (!strcasecmp(token, "allow"))
62e76326 2572 *var = URI_WHITESPACE_ALLOW;
d548ee64 2573 else if (!strcasecmp(token, "encode"))
62e76326 2574 *var = URI_WHITESPACE_ENCODE;
d548ee64 2575 else if (!strcasecmp(token, "chop"))
62e76326 2576 *var = URI_WHITESPACE_CHOP;
d548ee64 2577 else
62e76326 2578 self_destruct();
d548ee64 2579}
2580
d548ee64 2581static void
2582dump_uri_whitespace(StoreEntry * entry, const char *name, int var)
2583{
c193c972 2584 const char *s;
62e76326 2585
d548ee64 2586 if (var == URI_WHITESPACE_ALLOW)
62e76326 2587 s = "allow";
d548ee64 2588 else if (var == URI_WHITESPACE_ENCODE)
62e76326 2589 s = "encode";
d548ee64 2590 else if (var == URI_WHITESPACE_CHOP)
62e76326 2591 s = "chop";
7e3ce7b9 2592 else if (var == URI_WHITESPACE_DENY)
62e76326 2593 s = "deny";
7e3ce7b9 2594 else
62e76326 2595 s = "strip";
2596
d548ee64 2597 storeAppendPrintf(entry, "%s %s\n", name, s);
2598}
2599
6a566b9c 2600static void
c1dd71ae 2601free_removalpolicy(RemovalPolicySettings ** settings)
6a566b9c 2602{
2603 if (!*settings)
62e76326 2604 return;
2605
6a566b9c 2606 free_string(&(*settings)->type);
62e76326 2607
6a566b9c 2608 free_wordlist(&(*settings)->args);
62e76326 2609
c8f4eac4 2610 delete *settings;
62e76326 2611
6a566b9c 2612 *settings = NULL;
2613}
2614
2615static void
c1dd71ae 2616parse_removalpolicy(RemovalPolicySettings ** settings)
6a566b9c 2617{
2618 if (*settings)
62e76326 2619 free_removalpolicy(settings);
2620
c8f4eac4 2621 *settings = new RemovalPolicySettings;
62e76326 2622
6a566b9c 2623 parse_string(&(*settings)->type);
62e76326 2624
6a566b9c 2625 parse_wordlist(&(*settings)->args);
2626}
2627
2628static void
c1dd71ae 2629dump_removalpolicy(StoreEntry * entry, const char *name, RemovalPolicySettings * settings)
6a566b9c 2630{
2631 wordlist *args;
2632 storeAppendPrintf(entry, "%s %s", name, settings->type);
2633 args = settings->args;
62e76326 2634
6a566b9c 2635 while (args) {
62e76326 2636 storeAppendPrintf(entry, " %s", args->key);
2637 args = args->next;
6a566b9c 2638 }
62e76326 2639
be58afb5 2640 storeAppendPrintf(entry, "\n");
6a566b9c 2641}
c1dd71ae 2642
1ee67578 2643#include "cf_parser.h"
f1dc9b30 2644
2645peer_t
2646parseNeighborType(const char *s)
2647{
2648 if (!strcasecmp(s, "parent"))
62e76326 2649 return PEER_PARENT;
2650
f1dc9b30 2651 if (!strcasecmp(s, "neighbor"))
62e76326 2652 return PEER_SIBLING;
2653
f1dc9b30 2654 if (!strcasecmp(s, "neighbour"))
62e76326 2655 return PEER_SIBLING;
2656
f1dc9b30 2657 if (!strcasecmp(s, "sibling"))
62e76326 2658 return PEER_SIBLING;
2659
f1dc9b30 2660 if (!strcasecmp(s, "multicast"))
62e76326 2661 return PEER_MULTICAST;
2662
bf8fe701 2663 debugs(15, 0, "WARNING: Unknown neighbor type: " << s);
62e76326 2664
f1dc9b30 2665 return PEER_SIBLING;
2666}
f150dd4b 2667
0b0cfcf2 2668#if USE_WCCPv2
52f772de 2669void
2670parse_sockaddr_in_list_token(sockaddr_in_list ** head, char *token)
7e3ce7b9 2671{
7e3ce7b9 2672 char *t;
efd900cb 2673 char *host;
7d569f1b 2674 char *tmp;
62e76326 2675
7e3ce7b9 2676 const struct hostent *hp;
efd900cb 2677 unsigned short port;
7e3ce7b9 2678 sockaddr_in_list *s;
52f772de 2679
2680 host = NULL;
2681 port = 0;
62e76326 2682
52f772de 2683 if ((t = strchr(token, ':'))) {
62e76326 2684 /* host:port */
2685 host = token;
2686 *t = '\0';
0e656b69 2687 port = xatos(t + 1);
62e76326 2688
2689 if (0 == port)
2690 self_destruct();
7d569f1b 2691 } else if ((port = strtol(token, &tmp, 10)), !*tmp) {
62e76326 2692 /* port */
52f772de 2693 } else {
7d569f1b 2694 host = token;
0d5a2006 2695 port = 0;
52f772de 2696 }
62e76326 2697
e6ccf245 2698 s = static_cast<sockaddr_in_list *>(xcalloc(1, sizeof(*s)));
52f772de 2699 s->s.sin_port = htons(port);
62e76326 2700
52f772de 2701 if (NULL == host)
62e76326 2702 s->s.sin_addr = any_addr;
52f772de 2703 else if (1 == safe_inet_addr(host, &s->s.sin_addr))
62e76326 2704 (void) 0;
52f772de 2705 else if ((hp = gethostbyname(host))) /* dont use ipcache */
62e76326 2706 s->s.sin_addr = inaddrFromHostent(hp);
52f772de 2707 else
62e76326 2708 self_destruct();
2709
52f772de 2710 while (*head)
62e76326 2711 head = &(*head)->next;
2712
52f772de 2713 *head = s;
2714}
2715
2716static void
2717parse_sockaddr_in_list(sockaddr_in_list ** head)
2718{
2719 char *token;
62e76326 2720
52f772de 2721 while ((token = strtok(NULL, w_space))) {
62e76326 2722 parse_sockaddr_in_list_token(head, token);
7e3ce7b9 2723 }
2724}
2725
2726static void
2727dump_sockaddr_in_list(StoreEntry * e, const char *n, const sockaddr_in_list * s)
2728{
2729 while (s) {
62e76326 2730 storeAppendPrintf(e, "%s %s:%d\n",
2731 n,
2732 inet_ntoa(s->s.sin_addr),
2733 ntohs(s->s.sin_port));
2734 s = s->next;
7e3ce7b9 2735 }
2736}
2737
2738static void
2739free_sockaddr_in_list(sockaddr_in_list ** head)
2740{
2741 sockaddr_in_list *s;
62e76326 2742
7e3ce7b9 2743 while ((s = *head) != NULL) {
62e76326 2744 *head = s->next;
2745 xfree(s);
7e3ce7b9 2746 }
2747}
2748
0b0cfcf2 2749#if CURRENTLY_UNUSED
2750/* This code was previously used by http_port. Left as it really should
2751 * be used by icp_port and htcp_port
2752 */
7e3ce7b9 2753static int
2754check_null_sockaddr_in_list(const sockaddr_in_list * s)
2755{
2756 return NULL == s;
2757}
62e76326 2758
3f38a55e 2759#endif /* CURRENTLY_UNUSED */
0b0cfcf2 2760#endif /* USE_WCCPv2 */
7e3ce7b9 2761
d193a436 2762static void
3f38a55e 2763parse_http_port_specification(http_port_list * s, char *token)
d193a436 2764{
3f38a55e 2765 char *host = NULL;
62e76326 2766
d193a436 2767 const struct hostent *hp;
3f38a55e 2768 unsigned short port = 0;
2769 char *t;
62e76326 2770
5529ca8a 2771 s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
2772
d193a436 2773 if ((t = strchr(token, ':'))) {
62e76326 2774 /* host:port */
2775 host = token;
2776 *t = '\0';
0e656b69 2777 port = xatos(t + 1);
d193a436 2778 } else {
0e656b69 2779 /* port */
2780 port = xatos(token);
d193a436 2781 }
62e76326 2782
0e656b69 2783 if (port == 0)
2784 self_destruct();
2785
d193a436 2786 s->s.sin_port = htons(port);
62e76326 2787
d193a436 2788 if (NULL == host)
62e76326 2789 s->s.sin_addr = any_addr;
d193a436 2790 else if (1 == safe_inet_addr(host, &s->s.sin_addr))
62e76326 2791 (void) 0;
3f38a55e 2792 else if ((hp = gethostbyname(host))) {
62e76326 2793 /* dont use ipcache */
2794 s->s.sin_addr = inaddrFromHostent(hp);
2795 s->defaultsite = xstrdup(host);
3f38a55e 2796 } else
62e76326 2797 self_destruct();
3f38a55e 2798}
2799
2800static void
2801parse_http_port_option(http_port_list * s, char *token)
2802{
2803 if (strncmp(token, "defaultsite=", 12) == 0) {
62e76326 2804 safe_free(s->defaultsite);
2805 s->defaultsite = xstrdup(token + 12);
2806 s->accel = 1;
3f38a55e 2807 } else if (strncmp(token, "name=", 5) == 0) {
62e76326 2808 safe_free(s->name);
2809 s->name = xstrdup(token + 5);
3f38a55e 2810 } else if (strcmp(token, "transparent") == 0) {
62e76326 2811 s->transparent = 1;
3f38a55e 2812 } else if (strcmp(token, "vhost") == 0) {
62e76326 2813 s->vhost = 1;
2814 s->accel = 1;
3f38a55e 2815 } else if (strcmp(token, "vport") == 0) {
62e76326 2816 s->vport = -1;
2817 s->accel = 1;
3f38a55e 2818 } else if (strncmp(token, "vport=", 6) == 0) {
0e656b69 2819 s->vport = xatos(token + 6);
62e76326 2820 s->accel = 1;
3f38a55e 2821 } else if (strncmp(token, "protocol=", 9) == 0) {
62e76326 2822 s->protocol = xstrdup(token + 9);
2823 s->accel = 1;
3f38a55e 2824 } else if (strcmp(token, "accel") == 0) {
62e76326 2825 s->accel = 1;
5529ca8a 2826 } else if (strncmp(token, "disable-pmtu-discovery=", 23) == 0) {
2827 if (!strcasecmp(token + 23, "off"))
2828 s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
2829 else if (!strcasecmp(token + 23, "transparent"))
2830 s->disable_pmtu_discovery = DISABLE_PMTU_TRANSPARENT;
2831 else if (!strcasecmp(token + 23, "always"))
2832 s->disable_pmtu_discovery = DISABLE_PMTU_ALWAYS;
2833 else
2834 self_destruct();
fc68f6b1 2835
2836#if LINUX_TPROXY
2837
2838 } else if (strcmp(token, "tproxy") == 0) {
2839 s->tproxy = 1;
2840 need_linux_tproxy = 1;
2841#endif
2842
3f38a55e 2843 } else {
62e76326 2844 self_destruct();
3f38a55e 2845 }
2846}
2847
2848static void
2849free_generic_http_port_data(http_port_list * s)
2850{
2851 safe_free(s->name);
2852 safe_free(s->defaultsite);
f9ad0106 2853 safe_free(s->protocol);
3f38a55e 2854}
2855
2856static void
2857cbdataFree_http_port(void *data)
2858{
2859 free_generic_http_port_data((http_port_list *)data);
2860}
2861
3f38a55e 2862static http_port_list *
2863create_http_port(char *portspec)
2864{
2865 CBDATA_TYPE(http_port_list);
2866 CBDATA_INIT_TYPE_FREECB(http_port_list, cbdataFree_http_port);
2867
2868 http_port_list *s = cbdataAlloc(http_port_list);
2869 s->protocol = xstrdup("http");
2870 parse_http_port_specification(s, portspec);
2871 return s;
2872}
2873
2874void
2875add_http_port(char *portspec)
2876{
2877 http_port_list *s = create_http_port(portspec);
2878 s->next = Config.Sockaddr.http;
2879 Config.Sockaddr.http = s;
2880}
2881
2882static void
2883parse_http_port_list(http_port_list ** head)
2884{
2885 char *token = strtok(NULL, w_space);
62e76326 2886
9eeb8e4b 2887 if (!token) {
62e76326 2888 self_destruct();
9eeb8e4b 2889 return;
2890 }
62e76326 2891
3f38a55e 2892 http_port_list *s = create_http_port(token);
62e76326 2893
3f38a55e 2894 /* parse options ... */
2895 while ((token = strtok(NULL, w_space))) {
62e76326 2896 parse_http_port_option(s, token);
3f38a55e 2897 }
62e76326 2898
3f38a55e 2899 while (*head)
62e76326 2900 head = &(*head)->next;
2901
3f38a55e 2902 *head = s;
2903}
2904
2905static void
2906dump_generic_http_port(StoreEntry * e, const char *n, const http_port_list * s)
2907{
2908 storeAppendPrintf(e, "%s %s:%d",
62e76326 2909 n,
2910 inet_ntoa(s->s.sin_addr),
2911 ntohs(s->s.sin_port));
2912
3f38a55e 2913 if (s->defaultsite)
62e76326 2914 storeAppendPrintf(e, " defaultsite=%s", s->defaultsite);
2915
3f38a55e 2916 if (s->transparent)
62e76326 2917 storeAppendPrintf(e, " transparent");
2918
3f38a55e 2919 if (s->vhost)
62e76326 2920 storeAppendPrintf(e, " vhost");
2921
3f38a55e 2922 if (s->vport)
62e76326 2923 storeAppendPrintf(e, " vport");
5529ca8a 2924
2925 if (s->disable_pmtu_discovery != DISABLE_PMTU_OFF) {
2926 const char *pmtu;
2927
2928 if (s->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)
2929 pmtu = "always";
2930 else
2931 pmtu = "transparent";
2932
2933 storeAppendPrintf(e, " disable-pmtu-discovery=%s", pmtu);
2934 }
3f38a55e 2935}
62e76326 2936
3f38a55e 2937static void
2938dump_http_port_list(StoreEntry * e, const char *n, const http_port_list * s)
2939{
2940 while (s) {
62e76326 2941 dump_generic_http_port(e, n, s);
2942 storeAppendPrintf(e, "\n");
2943 s = s->next;
3f38a55e 2944 }
2945}
2946
2947static void
2948free_http_port_list(http_port_list ** head)
2949{
2950 http_port_list *s;
62e76326 2951
3f38a55e 2952 while ((s = *head) != NULL) {
62e76326 2953 *head = s->next;
2954 cbdataFree(s);
3f38a55e 2955 }
2956}
2957
3f38a55e 2958#if USE_SSL
2959static void
2960cbdataFree_https_port(void *data)
2961{
2962 https_port_list *s = (https_port_list *)data;
2963 free_generic_http_port_data(&s->http);
2964 safe_free(s->cert);
2965 safe_free(s->key);
f9ad0106 2966 safe_free(s->options);
2967 safe_free(s->cipher);
2968 safe_free(s->cafile);
2969 safe_free(s->capath);
2970 safe_free(s->dhfile);
2971 safe_free(s->sslflags);
3f38a55e 2972}
2973
2974static void
2975parse_https_port_list(https_port_list ** head)
2976{
2977 CBDATA_TYPE(https_port_list);
2978 char *token;
2979 https_port_list *s;
2980 CBDATA_INIT_TYPE_FREECB(https_port_list, cbdataFree_https_port);
2981 token = strtok(NULL, w_space);
62e76326 2982
3f38a55e 2983 if (!token)
62e76326 2984 self_destruct();
2985
3f38a55e 2986 s = cbdataAlloc(https_port_list);
62e76326 2987
3f38a55e 2988 s->http.protocol = xstrdup("https");
62e76326 2989
3f38a55e 2990 parse_http_port_specification(&s->http, token);
62e76326 2991
d193a436 2992 /* parse options ... */
2993 while ((token = strtok(NULL, w_space))) {
62e76326 2994 if (strncmp(token, "cert=", 5) == 0) {
2995 safe_free(s->cert);
2996 s->cert = xstrdup(token + 5);
2997 } else if (strncmp(token, "key=", 4) == 0) {
2998 safe_free(s->key);
2999 s->key = xstrdup(token + 4);
3000 } else if (strncmp(token, "version=", 8) == 0) {
3001 s->version = xatoi(token + 8);
8bbd476e 3002
3003 if (s->version < 1 || s->version > 4)
3004 self_destruct();
62e76326 3005 } else if (strncmp(token, "options=", 8) == 0) {
3006 safe_free(s->options);
3007 s->options = xstrdup(token + 8);
3008 } else if (strncmp(token, "cipher=", 7) == 0) {
3009 safe_free(s->cipher);
3010 s->cipher = xstrdup(token + 7);
3011 } else if (strncmp(token, "clientca=", 9) == 0) {
3012 safe_free(s->clientca);
3013 s->clientca = xstrdup(token + 9);
3014 } else if (strncmp(token, "cafile=", 7) == 0) {
3015 safe_free(s->cafile);
3016 s->cafile = xstrdup(token + 7);
3017 } else if (strncmp(token, "capath=", 7) == 0) {
3018 safe_free(s->capath);
3019 s->capath = xstrdup(token + 7);
a82a4fe4 3020 } else if (strncmp(token, "crlfile=", 8) == 0) {
3021 safe_free(s->crlfile);
3022 s->crlfile = xstrdup(token + 8);
35105e4b 3023 } else if (strncmp(token, "dhparams=", 9) == 0) {
3024 safe_free(s->dhfile);
3025 s->dhfile = xstrdup(token + 9);
62e76326 3026 } else if (strncmp(token, "sslflags=", 9) == 0) {
3027 safe_free(s->sslflags);
3028 s->sslflags = xstrdup(token + 9);
6b2936d5 3029 } else if (strncmp(token, "sslcontext=", 11) == 0) {
3030 safe_free(s->sslcontext);
3031 s->sslcontext = xstrdup(token + 11);
62e76326 3032 } else {
3033 parse_http_port_option(&s->http, token);
3034 }
d193a436 3035 }
62e76326 3036
8abf232c 3037 while (*head) {
3038 http_port_list ** headTmp = &(*head)->http.next;
3039 head = (https_port_list **)headTmp;
3040 }
62e76326 3041
d193a436 3042 *head = s;
3043}
3044
3045static void
3046dump_https_port_list(StoreEntry * e, const char *n, const https_port_list * s)
3047{
3048 while (s) {
62e76326 3049 dump_generic_http_port(e, n, &s->http);
3050
3051 if (s->cert)
3052 storeAppendPrintf(e, " cert=%s", s->cert);
3053
3054 if (s->key)
5c83dac8 3055 storeAppendPrintf(e, " key=%s", s->key);
62e76326 3056
3057 if (s->version)
3058 storeAppendPrintf(e, " version=%d", s->version);
3059
3060 if (s->options)
3061 storeAppendPrintf(e, " options=%s", s->options);
3062
3063 if (s->cipher)
3064 storeAppendPrintf(e, " cipher=%s", s->cipher);
3065
3066 if (s->cafile)
3067 storeAppendPrintf(e, " cafile=%s", s->cafile);
3068
3069 if (s->capath)
3070 storeAppendPrintf(e, " capath=%s", s->capath);
3071
a82a4fe4 3072 if (s->crlfile)
3073 storeAppendPrintf(e, " crlfile=%s", s->crlfile);
3074
35105e4b 3075 if (s->dhfile)
3076 storeAppendPrintf(e, " dhparams=%s", s->dhfile);
3077
62e76326 3078 if (s->sslflags)
3079 storeAppendPrintf(e, " sslflags=%s", s->sslflags);
3080
6b2936d5 3081 if (s->sslcontext)
3082 storeAppendPrintf(e, " sslcontext=%s", s->sslcontext);
3083
62e76326 3084 storeAppendPrintf(e, "\n");
3085
3086 s = (https_port_list *) s->http.next;
d193a436 3087 }
3088}
3089
3090static void
3091free_https_port_list(https_port_list ** head)
3092{
3093 https_port_list *s;
62e76326 3094
d193a436 3095 while ((s = *head) != NULL) {
62e76326 3096 *head = (https_port_list *) s->http.next;
3097 cbdataFree(s);
d193a436 3098 }
3099}
3100
3101#if 0
3102static int
3103check_null_https_port_list(const https_port_list * s)
3104{
3105 return NULL == s;
3106}
62e76326 3107
d193a436 3108#endif
3109
3110#endif /* USE_SSL */
3111
f150dd4b 3112void
3113configFreeMemory(void)
3114{
23ff6968 3115 free_all();
f150dd4b 3116}
f0b19334 3117
94439e4e 3118void
f0b19334 3119requirePathnameExists(const char *name, const char *path)
3120{
62e76326 3121
f0b19334 3122 struct stat sb;
08577e16 3123 char pathbuf[BUFSIZ];
f0b19334 3124 assert(path != NULL);
62e76326 3125
0b796acd 3126 if (Config.chroot_dir && (geteuid() == 0)) {
62e76326 3127 snprintf(pathbuf, BUFSIZ, "%s/%s", Config.chroot_dir, path);
3128 path = pathbuf;
08577e16 3129 }
62e76326 3130
a572d8be 3131 if (stat(path, &sb) < 0) {
3132 if (opt_send_signal == -1 || opt_send_signal == SIGHUP)
3133 fatalf("%s %s: %s", name, path, xstrerror());
3134 else
3135 fprintf(stderr, "WARNING: %s %s: %s\n", name, path, xstrerror());
3136 }
f0b19334 3137}
d860a1aa 3138
3139char *
3140strtokFile(void)
3141{
d295d770 3142 return ConfigParser::strtokFile();
d860a1aa 3143}
7684c4b1 3144
450e0c10 3145#include "AccessLogEntry.h"
3146/* TODO: split out parsing somehow ...*/
7684c4b1 3147static void
3148parse_logformat(logformat ** logformat_definitions)
3149{
3150 logformat *nlf;
3151 char *name, *def;
3152
3153 if ((name = strtok(NULL, w_space)) == NULL)
3154 self_destruct();
3155
9eeb8e4b 3156 if ((def = strtok(NULL, "\r\n")) == NULL) {
7684c4b1 3157 self_destruct();
9eeb8e4b 3158 return;
3159 }
7684c4b1 3160
bf8fe701 3161 debugs(3, 2, "Logformat for '" << name << "' is '" << def << "'");
7684c4b1 3162
3163 nlf = (logformat *)xcalloc(1, sizeof(logformat));
3164
3165 nlf->name = xstrdup(name);
3166
9eeb8e4b 3167 if (!accessLogParseLogFormat(&nlf->format, def)) {
7684c4b1 3168 self_destruct();
9eeb8e4b 3169 return;
3170 }
7684c4b1 3171
3172 nlf->next = *logformat_definitions;
3173
3174 *logformat_definitions = nlf;
3175}
3176
3177static void
3178parse_access_log(customlog ** logs)
3179{
3180 const char *filename, *logdef_name;
3181 customlog *cl;
3182 logformat *lf;
3183
3184 cl = (customlog *)xcalloc(1, sizeof(*cl));
3185
9eeb8e4b 3186 if ((filename = strtok(NULL, w_space)) == NULL) {
7684c4b1 3187 self_destruct();
9eeb8e4b 3188 return;
3189 }
7684c4b1 3190
3191 if (strcmp(filename, "none") == 0) {
3192 cl->type = CLF_NONE;
3193 goto done;
3194 }
3195
3196 if ((logdef_name = strtok(NULL, w_space)) == NULL)
3197 logdef_name = "auto";
3198
bf8fe701 3199 debugs(3, 9, "Log definition name '" << logdef_name << "' file '" << filename << "'");
7684c4b1 3200
3201 cl->filename = xstrdup(filename);
3202
3203 /* look for the definition pointer corresponding to this name */
3204 lf = Config.Log.logformats;
3205
3206 while (lf != NULL) {
bf8fe701 3207 debugs(3, 9, "Comparing against '" << lf->name << "'");
7684c4b1 3208
3209 if (strcmp(lf->name, logdef_name) == 0)
3210 break;
3211
3212 lf = lf->next;
3213 }
3214
3215 if (lf != NULL) {
3216 cl->type = CLF_CUSTOM;
3217 cl->logFormat = lf;
3218 } else if (strcmp(logdef_name, "auto") == 0) {
3219 cl->type = CLF_AUTO;
3220 } else if (strcmp(logdef_name, "squid") == 0) {
3221 cl->type = CLF_SQUID;
3222 } else if (strcmp(logdef_name, "common") == 0) {
3223 cl->type = CLF_COMMON;
3224 } else {
bf8fe701 3225 debugs(3, 0, "Log format '" << logdef_name << "' is not defined");
7684c4b1 3226 self_destruct();
9eeb8e4b 3227 return;
7684c4b1 3228 }
3229
3230done:
a9f20260 3231 aclParseAclList(LegacyParser, &cl->aclList);
7684c4b1 3232
3233 while (*logs)
3234 logs = &(*logs)->next;
3235
3236 *logs = cl;
3237}
3238
ca801547 3239#if UNUSED_CODE
d64bef4c 3240static int
3241check_null_access_log(customlog *customlog_definitions)
3242{
3243 return customlog_definitions == NULL;
3244}
ca801547 3245#endif
d64bef4c 3246
7684c4b1 3247static void
3248dump_logformat(StoreEntry * entry, const char *name, logformat * definitions)
3249{
3250 accessLogDumpLogFormat(entry, name, definitions);
3251}
3252
3253static void
3254dump_access_log(StoreEntry * entry, const char *name, customlog * logs)
3255{
3256 customlog *log;
3257
3258 for (log = logs; log; log = log->next) {
3259 storeAppendPrintf(entry, "%s ", name);
3260
3261 switch (log->type) {
3262
3263 case CLF_CUSTOM:
3264 storeAppendPrintf(entry, "%s %s", log->filename, log->logFormat->name);
3265 break;
3266
3267 case CLF_NONE:
3268 storeAppendPrintf(entry, "none");
3269 break;
3270
3271 case CLF_SQUID:
3272 storeAppendPrintf(entry, "%s squid", log->filename);
3273 break;
3274
3275 case CLF_COMMON:
3276 storeAppendPrintf(entry, "%s squid", log->filename);
3277 break;
3278
3279 case CLF_AUTO:
3280
3281 if (log->aclList)
3282 storeAppendPrintf(entry, "%s auto", log->filename);
3283 else
3284 storeAppendPrintf(entry, "%s", log->filename);
3285
3286 break;
3287
3288 case CLF_UNKNOWN:
3289 break;
3290 }
3291
3292 if (log->aclList)
3293 dump_acl_list(entry, log->aclList);
3294
3295 storeAppendPrintf(entry, "\n");
3296 }
3297}
3298
3299static void
3300free_logformat(logformat ** definitions)
3301{
3302 while (*definitions) {
3303 logformat *format = *definitions;
3304 *definitions = format->next;
3305 accessLogFreeLogFormat(&format->format);
3306 xfree(format);
3307 }
3308}
3309
3310static void
3311free_access_log(customlog ** definitions)
3312{
3313 while (*definitions) {
3314 customlog *log = *definitions;
3315 *definitions = log->next;
3316
3317 log->logFormat = NULL;
3318 log->type = CLF_UNKNOWN;
3319
3320 if (log->aclList)
3321 aclDestroyAclList(&log->aclList);
3322
3323 safe_free(log->filename);
3324
3325 xfree(log);
3326 }
3327}
3a69ddf3 3328
3329#if ICAP_CLIENT
3330
3331static void
3332parse_icap_service_type(ICAPConfig * cfg)
3333{
3334 cfg->parseICAPService();
3335}
3336
3337static void
3338free_icap_service_type(ICAPConfig * cfg)
3339{
3340 cfg->freeICAPService();
3341}
3342
3343static void
a99015b2 3344dump_icap_service_type(StoreEntry * entry, const char *name, const ICAPConfig &cfg)
3a69ddf3 3345{
3346 cfg.dumpICAPService(entry, name);
3347}
3348
3349static void
3350parse_icap_class_type(ICAPConfig * cfg)
3351{
3352 cfg->parseICAPClass();
3353}
3354
3355static void
3356free_icap_class_type(ICAPConfig * cfg)
3357{
3358 cfg->freeICAPClass();
3359}
3360
3361static void
a99015b2 3362dump_icap_class_type(StoreEntry * entry, const char *name, const ICAPConfig &cfg)
3a69ddf3 3363{
3364 cfg.dumpICAPClass(entry, name);
3365}
3366
3367static void
3368parse_icap_access_type(ICAPConfig * cfg)
3369{
a385afc3 3370 cfg->parseICAPAccess(LegacyParser);
3a69ddf3 3371}
3372
3373static void
3374free_icap_access_type(ICAPConfig * cfg)
3375{
3376 cfg->freeICAPAccess();
3377}
3378
3379static void
a99015b2 3380dump_icap_access_type(StoreEntry * entry, const char *name, const ICAPConfig &cfg)
3a69ddf3 3381{
3382 cfg.dumpICAPAccess(entry, name);
3383}
3384
3385#endif