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