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