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