]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cache_cf.cc
Bug #1347: Modify squid MIB to incorporate squid.conf visible_hostname
[thirdparty/squid.git] / src / cache_cf.cc
CommitLineData
be335c22 1
30a4f2a8 2/*
985c86bc 3 * $Id: cache_cf.cc,v 1.495 2006/05/08 23:38:33 robertc 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"
e6ccf245 40#include "Store.h"
d3b3ab85 41#include "SwapDir.h"
a80a77cf 42#include "ConfigParser.h"
8000a965 43#include "ACL.h"
59b2d47f 44#include "StoreFileSystem.h"
c8f4eac4 45#include "Parsing.h"
0eb49b6d 46#include "MemBuf.h"
d295d770 47#include "wordlist.h"
1df370e3 48
49#if SQUID_SNMP
a97cfa48 50#include "snmp.h"
1df370e3 51#endif
43ae1d95 52#if ESI
53#include "ESIParser.h"
54#endif
090089c4 55
3a69ddf3 56#if ICAP_CLIENT
57#include "ICAP/ICAPConfig.h"
58extern ICAPConfig TheICAPConfig; // for cf_parser.h
59
60static void parse_icap_service_type(ICAPConfig *);
61static void dump_icap_service_type(StoreEntry *, const char *, ICAPConfig );
62static void free_icap_service_type(ICAPConfig *);
63static void parse_icap_class_type(ICAPConfig *);
64static void dump_icap_class_type(StoreEntry *, const char *, ICAPConfig );
65static void free_icap_class_type(ICAPConfig *);
66static void parse_icap_access_type(ICAPConfig *);
67static void dump_icap_access_type(StoreEntry *, const char *, ICAPConfig );
68static void free_icap_access_type(ICAPConfig *);
69
70#endif
71
f5691f9c 72CBDATA_TYPE(peer);
73
8813e606 74static const char *const T_SECOND_STR = "second";
75static const char *const T_MINUTE_STR = "minute";
76static const char *const T_HOUR_STR = "hour";
77static const char *const T_DAY_STR = "day";
78static const char *const T_WEEK_STR = "week";
79static const char *const T_FORTNIGHT_STR = "fortnight";
80static const char *const T_MONTH_STR = "month";
81static const char *const T_YEAR_STR = "year";
82static const char *const T_DECADE_STR = "decade";
aa0a0c7c 83
9906e724 84static const char *const B_BYTES_STR = "bytes";
85static const char *const B_KBYTES_STR = "KB";
86static const char *const B_MBYTES_STR = "MB";
87static const char *const B_GBYTES_STR = "GB";
88
4db43fab 89static const char *const list_sep = ", \t\n\r";
b0e7d2d5 90
7684c4b1 91static void parse_logformat(logformat ** logformat_definitions);
92static void parse_access_log(customlog ** customlog_definitions);
d64bef4c 93static int check_null_access_log(customlog *customlog_definitions);
94
7684c4b1 95static void dump_logformat(StoreEntry * entry, const char *name, logformat * definitions);
96static void dump_access_log(StoreEntry * entry, const char *name, customlog * definitions);
97static void free_logformat(logformat ** definitions);
98static void free_access_log(customlog ** definitions);
99
cd748f27 100static void update_maxobjsize(void);
f5b8bbc4 101static void configDoConfigure(void);
102static void parse_refreshpattern(refresh_t **);
103static int parseTimeUnits(const char *unit);
104static void parseTimeLine(time_t * tptr, const char *units);
59715b38 105static void parse_ushort(u_short * var);
f5b8bbc4 106static void parse_string(char **);
f5b8bbc4 107static void default_all(void);
108static void defaults_if_none(void);
109static int parse_line(char *);
110static void parseBytesLine(size_t * bptr, const char *units);
111static size_t parseBytesUnits(const char *unit);
f5b8bbc4 112static void free_all(void);
94439e4e 113void requirePathnameExists(const char *name, const char *path);
ed7f5615 114static OBJH dump_config;
c26ffae9 115#if HTTP_VIOLATIONS
6bccf575 116static void dump_http_header_access(StoreEntry * entry, const char *name, header_mangler header[]);
117static void parse_http_header_access(header_mangler header[]);
118static void free_http_header_access(header_mangler header[]);
119static void dump_http_header_replace(StoreEntry * entry, const char *name, header_mangler header[]);
120static void parse_http_header_replace(header_mangler * header);
121static void free_http_header_replace(header_mangler * header);
9e8b2f1c 122#endif
6bccf575 123static void parse_denyinfo(acl_deny_info_list ** var);
124static void dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var);
125static void free_denyinfo(acl_deny_info_list ** var);
3f38a55e 126#if CURRENTLY_UNUSED
7e3ce7b9 127static void parse_sockaddr_in_list(sockaddr_in_list **);
128static void dump_sockaddr_in_list(StoreEntry *, const char *, const sockaddr_in_list *);
129static void free_sockaddr_in_list(sockaddr_in_list **);
130static int check_null_sockaddr_in_list(const sockaddr_in_list *);
3f38a55e 131#endif /* CURRENTLY_UNUSED */
132static void parse_http_port_list(http_port_list **);
133static void dump_http_port_list(StoreEntry *, const char *, const http_port_list *);
134static void free_http_port_list(http_port_list **);
135#if UNUSED_CODE
136static int check_null_http_port_list(const http_port_list *);
52f772de 137#endif
d193a436 138#if USE_SSL
139static void parse_https_port_list(https_port_list **);
140static void dump_https_port_list(StoreEntry *, const char *, const https_port_list *);
141static void free_https_port_list(https_port_list **);
142#if 0
143static int check_null_https_port_list(const https_port_list *);
144#endif
145#endif /* USE_SSL */
ef1955a5 146static void parse_b_size_t(size_t * var);
270b86af 147
a385afc3 148/*
149 * LegacyParser is a parser for legacy code that uses the global
150 * approach. This is static so that it is only exposed to cache_cf.
151 * Other modules needing access to a ConfigParser should have it
152 * provided to them in their parserFOO methods.
153 */
154static ConfigParser LegacyParser = ConfigParser();
a9f20260 155
0e4e0e7d 156void
0673c0ba 157self_destruct(void)
090089c4 158{
a9f20260 159 LegacyParser.destruct();
6b8e7481 160}
161
3c5557f9 162/*
5c20d6fa 163 * These functions is the same as atoi/l/f, except that they check for errors
3c5557f9 164 */
090089c4 165
5c20d6fa 166static double
167xatof(const char *token)
168{
169 char *end;
170 double ret = strtod(token, &end);
62e76326 171
5c20d6fa 172 if (ret == 0 && end == token)
62e76326 173 self_destruct();
174
5c20d6fa 175 return ret;
176}
177
cd748f27 178static void
179update_maxobjsize(void)
180{
181 int i;
e8dbac8b 182 ssize_t ms = -1;
cd748f27 183
184 for (i = 0; i < Config.cacheSwap.n_configured; i++) {
c8f4eac4 185 assert (Config.cacheSwap.swapDirs[i].getRaw());
62e76326 186
c8f4eac4 187 if (dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->
188 max_objsize > ms)
189 ms = dynamic_cast<SwapDir *>(Config.cacheSwap.swapDirs[i].getRaw())->max_objsize;
cd748f27 190 }
62e76326 191
cd748f27 192 store_maxobjsize = ms;
193}
194
76b9daa5 195static void
196SetConfigFilename(char const *file_name, bool is_pipe)
197{
198 cfg_filename = file_name;
199
200 char const *token;
201
202 if (is_pipe)
203 cfg_filename = file_name + 1;
204 else if ((token = strrchr(cfg_filename, '/')))
205 cfg_filename = token + 1;
206}
207
270b86af 208int
209parseConfigFile(const char *file_name)
2546fcb3 210{
270b86af 211 FILE *fp = NULL;
212 char *token = NULL;
72121e8b 213 char *tmp_line;
e13ee7ad 214 int err_count = 0;
1741cbad 215 int is_pipe = 0;
42bf7c64 216 configFreeMemory();
0153d498 217 default_all();
62e76326 218
1741cbad 219 if (file_name[0] == '!' || file_name[0] == '|') {
62e76326 220 fp = popen(file_name + 1, "r");
221 is_pipe = 1;
1741cbad 222 } else {
62e76326 223 fp = fopen(file_name, "r");
1741cbad 224 }
62e76326 225
1741cbad 226 if (fp == NULL)
62e76326 227 fatalf("Unable to open configuration file: %s: %s",
228 file_name, xstrerror());
229
ec4daaa5 230#ifdef _SQUID_WIN32_
62e76326 231
c4aefe96 232 setmode(fileno(fp), O_TEXT);
62e76326 233
c4aefe96 234#endif
62e76326 235
76b9daa5 236 SetConfigFilename(file_name, bool(is_pipe));
62e76326 237
270b86af 238 memset(config_input_line, '\0', BUFSIZ);
62e76326 239
270b86af 240 config_lineno = 0;
62e76326 241
270b86af 242 while (fgets(config_input_line, BUFSIZ, fp)) {
62e76326 243 config_lineno++;
244
245 if ((token = strchr(config_input_line, '\n')))
246 *token = '\0';
247
d866e2ad 248 if ((token = strchr(config_input_line, '\r')))
249 *token = '\0';
250
62e76326 251 if (strncmp(config_input_line, "#line ", 6) == 0) {
252 static char new_file_name[1024];
253 static char *file;
254 static char new_lineno;
255 token = config_input_line + 6;
256 new_lineno = strtol(token, &file, 0) - 1;
257
258 if (file == token)
259 continue; /* Not a valid #line directive, may be a comment */
260
261 while (*file && isspace((unsigned char) *file))
262 file++;
263
264 if (*file) {
265 if (*file != '"')
266 continue; /* Not a valid #line directive, may be a comment */
267
268 xstrncpy(new_file_name, file + 1, sizeof(new_file_name));
269
270 if ((token = strchr(new_file_name, '"')))
271 *token = '\0';
272
273 cfg_filename = new_file_name;
274
1741cbad 275#if PROBABLY_NOT_WANTED_HERE
62e76326 276
76b9daa5 277 SetConfigFilename(cfg_filename, false);
62e76326 278
1741cbad 279#endif
62e76326 280
281 }
282
283 config_lineno = new_lineno;
284 }
285
286 if (config_input_line[0] == '#')
287 continue;
288
289 if (config_input_line[0] == '\0')
290 continue;
291
292 debug(3, 5) ("Processing: '%s'\n", config_input_line);
293
294 tmp_line = xstrdup(config_input_line);
295
296 if (!parse_line(tmp_line)) {
297 debug(3, 0) ("parseConfigFile: '%s' line %d unrecognized: '%s'\n",
298 cfg_filename,
299 config_lineno,
300 config_input_line);
301 err_count++;
302 }
303
304 safe_free(tmp_line);
270b86af 305 }
62e76326 306
1741cbad 307 if (is_pipe) {
62e76326 308 int ret = pclose(fp);
309
310 if (ret != 0)
311 fatalf("parseConfigFile: '%s' failed with exit code %d\n", file_name, ret);
1741cbad 312 } else {
62e76326 313 fclose(fp);
1741cbad 314 }
62e76326 315
f0b19334 316 defaults_if_none();
f9ad0106 317
318 if (!Config.chroot_dir) {
319 leave_suid();
320 _db_init(Config.Log.log, Config.debugOptions);
321 enter_suid();
322 }
323
a572d8be 324 configDoConfigure();
325
478c4f2f 326 if (opt_send_signal == -1) {
478c4f2f 327 cachemgrRegister("config",
328 "Current Squid Configuration",
329 dump_config,
330 1, 1);
331 }
332
e13ee7ad 333 return err_count;
f0b19334 334}
270b86af 335
f0b19334 336static void
337configDoConfigure(void)
338{
f0b19334 339 memset(&Config2, '\0', sizeof(SquidConfig2));
7021844c 340 /* init memory as early as possible */
341 memConfigure();
270b86af 342 /* Sanity checks */
62e76326 343
a95856a0 344 if (Config.cacheSwap.swapDirs == NULL)
62e76326 345 fatal("No cache_dir's specified in config file");
346
c8f4eac4 347 if (0 == Store::Root().maxSize())
62e76326 348 /* people might want a zero-sized cache on purpose */
349 (void) 0;
c8f4eac4 350 else if (Store::Root().maxSize() < (Config.memMaxSize >> 10))
351 /* This is bogus. folk with NULL caches will want this */
62e76326 352 debug(3, 0) ("WARNING cache_mem is larger than total disk cache space!\n");
353
84f42bac 354 if (Config.Announce.period > 0) {
62e76326 355 Config.onoff.announce = 1;
84f42bac 356 } else if (Config.Announce.period < 1) {
62e76326 357 Config.Announce.period = 86400 * 365; /* one year */
358 Config.onoff.announce = 0;
270b86af 359 }
62e76326 360
d3caee79 361 if (Config.onoff.httpd_suppress_version_string)
362 visible_appname_string = (char *)appname_string;
363 else
364 visible_appname_string = (char *)full_appname_string;
365
6b53c392 366#if USE_DNSSERVERS
d3caee79 367
f0b19334 368 if (Config.dnsChildren < 1)
62e76326 369 fatal("No dnsservers allocated");
370
efd900cb 371#endif
62e76326 372
270b86af 373 if (Config.Program.redirect) {
62e76326 374 if (Config.redirectChildren < 1) {
375 Config.redirectChildren = 0;
376 wordlistDestroy(&Config.Program.redirect);
377 }
fea2e6e0 378 }
62e76326 379
f1dc9b30 380 if (Config.appendDomain)
62e76326 381 if (*Config.appendDomain != '.')
382 fatal("append_domain must begin with a '.'");
383
270b86af 384 if (Config.errHtmlText == NULL)
62e76326 385 Config.errHtmlText = xstrdup(null_string);
386
270b86af 387 storeConfigure();
62e76326 388
52f772de 389 snprintf(ThisCache, sizeof(ThisCache), "%s (%s)",
62e76326 390 uniqueHostname(),
d3caee79 391 visible_appname_string);
fbdba7c4 392
38a6c74e 393 /*
394 * the extra space is for loop detection in client_side.c -- we search
395 * for substrings in the Via header.
396 */
52f772de 397 snprintf(ThisCache2, sizeof(ThisCache), " %s (%s)",
62e76326 398 uniqueHostname(),
d3caee79 399 visible_appname_string);
62e76326 400
270b86af 401 if (!Config.udpMaxHitObjsz || Config.udpMaxHitObjsz > SQUID_UDP_SO_SNDBUF)
62e76326 402 Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF;
403
270b86af 404 if (Config.appendDomain)
62e76326 405 Config.appendDomainLen = strlen(Config.appendDomain);
270b86af 406 else
62e76326 407 Config.appendDomainLen = 0;
408
f1dc9b30 409 safe_free(debug_options)
62e76326 410 debug_options = xstrdup(Config.debugOptions);
411
22c653cd 412 if (Config.retry.maxtries > 10)
62e76326 413 fatal("maximum_single_addr_tries cannot be larger than 10");
414
22c653cd 415 if (Config.retry.maxtries < 1) {
62e76326 416 debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n");
417 Config.retry.maxtries = 1;
5210854d 418 }
62e76326 419
f0b19334 420 requirePathnameExists("MIME Config Table", Config.mimeTablePathname);
6b53c392 421#if USE_DNSSERVERS
62e76326 422
f0b19334 423 requirePathnameExists("cache_dns_program", Config.Program.dnsserver);
efd900cb 424#endif
a3d0a19d 425#if USE_UNLINKD
62e76326 426
f0b19334 427 requirePathnameExists("unlinkd_program", Config.Program.unlinkd);
a3d0a19d 428#endif
62e76326 429
f0b19334 430 if (Config.Program.redirect)
62e76326 431 requirePathnameExists("redirect_program", Config.Program.redirect->key);
432
f0b19334 433 requirePathnameExists("Icon Directory", Config.icons.directory);
62e76326 434
f0b19334 435 requirePathnameExists("Error Directory", Config.errorDirectory);
62e76326 436
9f60cfdf 437#if HTTP_VIOLATIONS
62e76326 438
9f60cfdf 439 {
62e76326 440 const refresh_t *R;
441
442 for (R = Config.Refresh; R; R = R->next)
443 {
444 if (!R->flags.override_expire)
445 continue;
446
447 debug(22, 1) ("WARNING: use of 'override-expire' in 'refresh_pattern' violates HTTP\n");
448
449 break;
450 }
451
452 for (R = Config.Refresh; R; R = R->next)
453 {
454 if (!R->flags.override_lastmod)
455 continue;
456
457 debug(22, 1) ("WARNING: use of 'override-lastmod' in 'refresh_pattern' violates HTTP\n");
458
459 break;
460 }
461
38f9c547 462 for (R = Config.Refresh; R; R = R->next)
463 {
464 if (!R->flags.reload_into_ims)
465 continue;
466
467 debug(22, 1) ("WARNING: use of 'reload-into-ims' in 'refresh_pattern' violates HTTP\n");
468
469 break;
470 }
471
472 for (R = Config.Refresh; R; R = R->next)
473 {
474 if (!R->flags.ignore_reload)
475 continue;
476
477 debug(22, 1) ("WARNING: use of 'ignore-reload' in 'refresh_pattern' violates HTTP\n");
478
479 break;
480 }
481
482 for (R = Config.Refresh; R; R = R->next)
483 {
484 if (!R->flags.ignore_no_cache)
485 continue;
486
487 debug(22, 1) ("WARNING: use of 'ignore-no-cache' in 'refresh_pattern' violates HTTP\n");
488
489 break;
490 }
491
492 for (R = Config.Refresh; R; R = R->next)
493 {
494 if (!R->flags.ignore_no_store)
495 continue;
496
497 debug(22, 1) ("WARNING: use of 'ignore-no-store' in 'refresh_pattern' violates HTTP\n");
498
499 break;
500 }
501
502 for (R = Config.Refresh; R; R = R->next)
503 {
504 if (!R->flags.ignore_private)
505 continue;
506
507 debug(22, 1) ("WARNING: use of 'ignore-private' in 'refresh_pattern' violates HTTP\n");
508
509 break;
510 }
511
512 for (R = Config.Refresh; R; R = R->next)
513 {
514 if (!R->flags.ignore_auth)
515 continue;
516
517 debug(22, 1) ("WARNING: use of 'ignore-auth' in 'refresh_pattern' violates HTTP\n");
518
519 break;
520 }
521
9f60cfdf 522 }
c2f5c744 523#endif
524#if !HTTP_VIOLATIONS
525 Config.onoff.via = 1;
526#else
62e76326 527
c2f5c744 528 if (!Config.onoff.via)
62e76326 529 debug(22, 1) ("WARNING: HTTP requires the use of Via\n");
530
9f60cfdf 531#endif
62e76326 532
db1cd23c 533 if (Config.Wais.relayHost) {
62e76326 534 if (Config.Wais._peer)
535 cbdataFree(Config.Wais._peer);
536
f5691f9c 537 CBDATA_INIT_TYPE_FREECB(peer, peerDestroy);
538
62e76326 539 Config.Wais._peer = cbdataAlloc(peer);
540
541 Config.Wais._peer->host = xstrdup(Config.Wais.relayHost);
542
543 Config.Wais._peer->http_port = Config.Wais.relayPort;
db1cd23c 544 }
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;
7813c6d5 1469 int i;
f5691f9c 1470 CBDATA_INIT_TYPE_FREECB(peer, peerDestroy);
72711e31 1471 p = cbdataAlloc(peer);
40a1495e 1472 p->http_port = CACHE_HTTP_PORT;
399cabec 1473 p->icp.port = CACHE_ICP_PORT;
40a1495e 1474 p->weight = 1;
d1b63fc8 1475 p->basetime = 0;
dc835977 1476 p->stats.logged_state = PEER_ALIVE;
62e76326 1477
e481c2dc 1478 if ((token = strtok(NULL, w_space)) == NULL)
62e76326 1479 self_destruct();
1480
40a1495e 1481 p->host = xstrdup(token);
62e76326 1482
be753325 1483 p->name = xstrdup(token);
62e76326 1484
e481c2dc 1485 if ((token = strtok(NULL, w_space)) == NULL)
62e76326 1486 self_destruct();
1487
40a1495e 1488 p->type = parseNeighborType(token);
62e76326 1489
0e4e0e7d 1490 i = GetInteger();
62e76326 1491
40a1495e 1492 p->http_port = (u_short) i;
62e76326 1493
0e4e0e7d 1494 i = GetInteger();
62e76326 1495
399cabec 1496 p->icp.port = (u_short) i;
62e76326 1497
270b86af 1498 while ((token = strtok(NULL, w_space))) {
62e76326 1499 if (!strcasecmp(token, "proxy-only")) {
1500 p->options.proxy_only = 1;
1501 } else if (!strcasecmp(token, "no-query")) {
1502 p->options.no_query = 1;
1503 } else if (!strcasecmp(token, "background-ping")) {
1504 p->options.background_ping = 1;
1505 } else if (!strcasecmp(token, "no-digest")) {
1506 p->options.no_digest = 1;
1507 } else if (!strcasecmp(token, "multicast-responder")) {
1508 p->options.mcast_responder = 1;
1509 } else if (!strncasecmp(token, "weight=", 7)) {
1510 p->weight = xatoi(token + 7);
1511 } else if (!strncasecmp(token, "basetime=", 9)) {
1512 p->basetime = xatoi(token + 9);
1513 } else if (!strcasecmp(token, "closest-only")) {
1514 p->options.closest_only = 1;
1515 } else if (!strncasecmp(token, "ttl=", 4)) {
1516 p->mcast.ttl = xatoi(token + 4);
1517
1518 if (p->mcast.ttl < 0)
1519 p->mcast.ttl = 0;
1520
1521 if (p->mcast.ttl > 128)
1522 p->mcast.ttl = 128;
1523 } else if (!strcasecmp(token, "default")) {
1524 p->options.default_parent = 1;
1525 } else if (!strcasecmp(token, "round-robin")) {
1526 p->options.roundrobin = 1;
1527 } else if (!strcasecmp(token, "weighted-round-robin")) {
1528 p->options.weighted_roundrobin = 1;
dc9d133b 1529#if USE_HTCP
62e76326 1530
1531 } else if (!strcasecmp(token, "htcp")) {
1532 p->options.htcp = 1;
dc9d133b 1533#endif
62e76326 1534
1535 } else if (!strcasecmp(token, "no-netdb-exchange")) {
1536 p->options.no_netdb_exchange = 1;
afd88fbe 1537#if USE_CARP
62e76326 1538
1539 } else if (!strcasecmp(token, "carp")) {
1540 if (p->type != PEER_PARENT)
1541 fatalf("parse_peer: non-parent carp peer %s/%d\n", p->host, p->http_port);
1542
1543 p->options.carp = 1;
1544
95e36d02 1545#endif
1546#if DELAY_POOLS
62e76326 1547
1548 } else if (!strcasecmp(token, "no-delay")) {
1549 p->options.no_delay = 1;
afd88fbe 1550#endif
62e76326 1551
1552 } else if (!strncasecmp(token, "login=", 6)) {
1553 p->login = xstrdup(token + 6);
1554 rfc1738_unescape(p->login);
1555 } else if (!strncasecmp(token, "connect-timeout=", 16)) {
1556 p->connect_timeout = xatoi(token + 16);
7e3ce7b9 1557#if USE_CACHE_DIGESTS
62e76326 1558
1559 } else if (!strncasecmp(token, "digest-url=", 11)) {
1560 p->digest_url = xstrdup(token + 11);
7e3ce7b9 1561#endif
62e76326 1562
1563 } else if (!strcasecmp(token, "allow-miss")) {
1564 p->options.allow_miss = 1;
1565 } else if (!strncasecmp(token, "max-conn=", 9)) {
1566 p->max_conn = xatoi(token + 9);
1567 } else if (!strcasecmp(token, "originserver")) {
1568 p->options.originserver = 1;
1569 } else if (!strncasecmp(token, "name=", 5)) {
1570 safe_free(p->name);
1571
1572 if (token[5])
1573 p->name = xstrdup(token + 5);
1574 } else if (!strncasecmp(token, "forceddomain=", 13)) {
1575 safe_free(p->domain);
1576
1577 if (token[13])
1578 p->domain = xstrdup(token + 13);
1579
a7ad6e4e 1580#if USE_SSL
62e76326 1581
1582 } else if (strcmp(token, "ssl") == 0) {
1583 p->use_ssl = 1;
1584 } else if (strncmp(token, "sslcert=", 8) == 0) {
1585 safe_free(p->sslcert);
1586 p->sslcert = xstrdup(token + 8);
1587 } else if (strncmp(token, "sslkey=", 7) == 0) {
1588 safe_free(p->sslkey);
1589 p->sslkey = xstrdup(token + 7);
1590 } else if (strncmp(token, "sslversion=", 11) == 0) {
1591 p->sslversion = atoi(token + 11);
1592 } else if (strncmp(token, "ssloptions=", 11) == 0) {
1593 safe_free(p->ssloptions);
1594 p->ssloptions = xstrdup(token + 11);
1595 } else if (strncmp(token, "sslcipher=", 10) == 0) {
1596 safe_free(p->sslcipher);
1597 p->sslcipher = xstrdup(token + 10);
1598 } else if (strncmp(token, "sslcafile=", 10) == 0) {
1599 safe_free(p->sslcafile);
a82a4fe4 1600 p->sslcafile = xstrdup(token + 10);
62e76326 1601 } else if (strncmp(token, "sslcapath=", 10) == 0) {
1602 safe_free(p->sslcapath);
a82a4fe4 1603 p->sslcapath = xstrdup(token + 10);
1604 } else if (strncmp(token, "sslcrlfile=", 11) == 0) {
1605 safe_free(p->sslcrlfile);
1606 p->sslcapath = xstrdup(token + 10);
62e76326 1607 } else if (strncmp(token, "sslflags=", 9) == 0) {
1608 safe_free(p->sslflags);
1609 p->sslflags = xstrdup(token + 9);
1610 } else if (strncmp(token, "ssldomain=", 10) == 0) {
1611 safe_free(p->ssldomain);
1612 p->ssldomain = xstrdup(token + 10);
a7ad6e4e 1613#endif
62e76326 1614
1615 } else if (strcmp(token, "front-end-https") == 0) {
1616 p->front_end_https = 1;
1617 } else if (strcmp(token, "front-end-https=on") == 0) {
1618 p->front_end_https = 1;
1619 } else if (strcmp(token, "front-end-https=auto") == 0) {
1620 p->front_end_https = 2;
1621 } else {
1622 debug(3, 0) ("parse_peer: token='%s'\n", token);
1623 self_destruct();
1624 }
270b86af 1625 }
62e76326 1626
be753325 1627 if (peerFindByName(p->name))
62e76326 1628 fatalf("ERROR: cache_peer %s specified twice\n", p->name);
1629
40a1495e 1630 if (p->weight < 1)
62e76326 1631 p->weight = 1;
1632
399cabec 1633 p->icp.version = ICP_VERSION_CURRENT;
62e76326 1634
98829f69 1635 p->tcp_up = PEER_TCP_MAGIC_COUNT;
62e76326 1636
eb406bb7 1637 p->test_fd = -1;
62e76326 1638
e13ee7ad 1639#if USE_CACHE_DIGESTS
62e76326 1640
e13ee7ad 1641 if (!p->options.no_digest) {
62e76326 1642 /* XXX This looks odd.. who has the original pointer
1643 * then?
1644 */
1645 PeerDigest *pd = peerDigestCreate(p);
1646 p->digest = cbdataReference(pd);
8a6218c6 1647 }
62e76326 1648
e13ee7ad 1649#endif
0153d498 1650 while (*head != NULL)
62e76326 1651 head = &(*head)->next;
1652
0153d498 1653 *head = p;
62e76326 1654
40a1495e 1655 Config.npeers++;
62e76326 1656
82056f1e 1657 peerClearRR(p);
0153d498 1658}
1659
1660static void
40a1495e 1661free_peer(peer ** P)
0153d498 1662{
40a1495e 1663 peer *p;
62e76326 1664
79d39a72 1665 while ((p = *P) != NULL) {
62e76326 1666 *P = p->next;
3855c318 1667#if USE_CACHE_DIGESTS
62e76326 1668
1669 cbdataReferenceDone(p->digest);
3855c318 1670#endif
62e76326 1671
1672 cbdataFree(p);
a47b9029 1673 }
62e76326 1674
987c67d1 1675 Config.npeers = 0;
270b86af 1676}
1677
1678static void
a7d59104 1679dump_cachemgrpasswd(StoreEntry * entry, const char *name, cachemgr_passwd * list)
270b86af 1680{
d41de3c1 1681 wordlist *w;
62e76326 1682
d41de3c1 1683 while (list != NULL) {
62e76326 1684 if (strcmp(list->passwd, "none") && strcmp(list->passwd, "disable"))
1685 storeAppendPrintf(entry, "%s XXXXXXXXXX", name);
1686 else
1687 storeAppendPrintf(entry, "%s %s", name, list->passwd);
1688
1689 for (w = list->actions; w != NULL; w = w->next) {
1690 storeAppendPrintf(entry, " %s", w->key);
1691 }
1692
1693 storeAppendPrintf(entry, "\n");
1694 list = list->next;
d41de3c1 1695 }
270b86af 1696}
1697
1698static void
a47b9029 1699parse_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 1700{
1701 char *passwd = NULL;
1702 wordlist *actions = NULL;
22f3fd98 1703 cachemgr_passwd *p;
1704 cachemgr_passwd **P;
270b86af 1705 parse_string(&passwd);
1706 parse_wordlist(&actions);
e6ccf245 1707 p = static_cast<cachemgr_passwd *>(xcalloc(1, sizeof(cachemgr_passwd)));
22f3fd98 1708 p->passwd = passwd;
1709 p->actions = actions;
62e76326 1710
26aa7e31 1711 for (P = head; *P; P = &(*P)->next) {
62e76326 1712 /*
1713 * See if any of the actions from this line already have a
1714 * password from previous lines. The password checking
1715 * routines in cache_manager.c take the the password from
1716 * the first cachemgr_passwd struct that contains the
1717 * requested action. Thus, we should warn users who might
1718 * think they can have two passwords for the same action.
1719 */
1720 wordlist *w;
1721 wordlist *u;
1722
1723 for (w = (*P)->actions; w; w = w->next) {
1724 for (u = actions; u; u = u->next) {
1725 if (strcmp(w->key, u->key))
1726 continue;
1727
1728 debug(0, 0) ("WARNING: action '%s' (line %d) already has a password\n",
1729 u->key, config_lineno);
1730 }
1731 }
26aa7e31 1732 }
62e76326 1733
22f3fd98 1734 *P = p;
270b86af 1735}
1736
1737static void
a47b9029 1738free_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 1739{
a47b9029 1740 cachemgr_passwd *p;
62e76326 1741
79d39a72 1742 while ((p = *head) != NULL) {
62e76326 1743 *head = p->next;
1744 xfree(p->passwd);
1745 wordlistDestroy(&p->actions);
1746 xfree(p);
a47b9029 1747 }
270b86af 1748}
1749
8203a132 1750static void
16300b58 1751dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var)
270b86af 1752{
d41de3c1 1753 acl_name_list *a;
62e76326 1754
d41de3c1 1755 while (var != NULL) {
62e76326 1756 storeAppendPrintf(entry, "%s %s", name, var->err_page_name);
1757
1758 for (a = var->acl_list; a != NULL; a = a->next)
1759 storeAppendPrintf(entry, " %s", a->name);
1760
1761 storeAppendPrintf(entry, "\n");
1762
1763 var = var->next;
d41de3c1 1764 }
270b86af 1765}
1766
1767static void
16300b58 1768parse_denyinfo(acl_deny_info_list ** var)
6e40f263 1769{
f1dc9b30 1770 aclParseDenyInfoLine(var);
6e40f263 1771}
403279e0 1772
1273d501 1773void
a47b9029 1774free_denyinfo(acl_deny_info_list ** list)
3c5557f9 1775{
56b63fa1 1776 acl_deny_info_list *a = NULL;
1777 acl_deny_info_list *a_next = NULL;
1778 acl_name_list *l = NULL;
1779 acl_name_list *l_next = NULL;
62e76326 1780
1273d501 1781 for (a = *list; a; a = a_next) {
62e76326 1782 for (l = a->acl_list; l; l = l_next) {
1783 l_next = l->next;
1784 memFree(l, MEM_ACL_NAME_LIST);
1785 l = NULL;
1786 }
1787
1788 a_next = a->next;
1789 memFree(a, MEM_ACL_DENY_INFO_LIST);
1790 a = NULL;
1273d501 1791 }
62e76326 1792
1273d501 1793 *list = NULL;
270b86af 1794}
1795
1796static void
505e35db 1797parse_peer_access(void)
270b86af 1798{
1799 char *host = NULL;
505e35db 1800 peer *p;
62e76326 1801
270b86af 1802 if (!(host = strtok(NULL, w_space)))
62e76326 1803 self_destruct();
1804
0cdcddb9 1805 if ((p = peerFindByName(host)) == NULL) {
62e76326 1806 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
1807 cfg_filename, config_lineno, host);
1808 return;
0cdcddb9 1809 }
62e76326 1810
a9f20260 1811 aclParseAccessLine(LegacyParser, &p->access);
270b86af 1812}
1813
270b86af 1814static void
1815parse_hostdomain(void)
1816{
1817 char *host = NULL;
1818 char *domain = NULL;
62e76326 1819
270b86af 1820 if (!(host = strtok(NULL, w_space)))
62e76326 1821 self_destruct();
1822
f1dc9b30 1823 while ((domain = strtok(NULL, list_sep))) {
62e76326 1824 domain_ping *l = NULL;
1825 domain_ping **L = NULL;
1826 peer *p;
1827
1828 if ((p = peerFindByName(host)) == NULL) {
1829 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
1830 cfg_filename, config_lineno, host);
1831 continue;
1832 }
1833
1834 l = static_cast<domain_ping *>(xcalloc(1, sizeof(domain_ping)));
1835 l->do_ping = 1;
1836
1837 if (*domain == '!') { /* check for !.edu */
1838 l->do_ping = 0;
1839 domain++;
1840 }
1841
1842 l->domain = xstrdup(domain);
1843
1844 for (L = &(p->peer_domain); *L; L = &((*L)->next))
1845
1846 ;
1847 *L = l;
f1dc9b30 1848 }
270b86af 1849}
1850
1851static void
1852parse_hostdomaintype(void)
1853{
1854 char *host = NULL;
1855 char *type = NULL;
1856 char *domain = NULL;
62e76326 1857
270b86af 1858 if (!(host = strtok(NULL, w_space)))
62e76326 1859 self_destruct();
1860
270b86af 1861 if (!(type = strtok(NULL, w_space)))
62e76326 1862 self_destruct();
1863
f1dc9b30 1864 while ((domain = strtok(NULL, list_sep))) {
62e76326 1865 domain_type *l = NULL;
1866 domain_type **L = NULL;
1867 peer *p;
1868
1869 if ((p = peerFindByName(host)) == NULL) {
1870 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
1871 cfg_filename, config_lineno, host);
1872 return;
1873 }
1874
1875 l = static_cast<domain_type *>(xcalloc(1, sizeof(domain_type)));
1876 l->type = parseNeighborType(type);
1877 l->domain = xstrdup(domain);
1878
1879 for (L = &(p->typelist); *L; L = &((*L)->next))
1880
1881 ;
1882 *L = l;
f1dc9b30 1883 }
270b86af 1884}
1885
7e3ce7b9 1886#if UNUSED_CODE
270b86af 1887static void
a7d59104 1888dump_ushortlist(StoreEntry * entry, const char *name, ushortlist * u)
090089c4 1889{
270b86af 1890 while (u) {
62e76326 1891 storeAppendPrintf(entry, "%s %d\n", name, (int) u->i);
1892 u = u->next;
270b86af 1893 }
1894}
090089c4 1895
f53b06f9 1896static int
1897check_null_ushortlist(ushortlist * u)
1898{
1899 return u == NULL;
1900}
1901
270b86af 1902static void
1903parse_ushortlist(ushortlist ** P)
1904{
1905 char *token;
1906 int i;
1907 ushortlist *u;
1908 ushortlist **U;
62e76326 1909
270b86af 1910 while ((token = strtok(NULL, w_space))) {
62e76326 1911 if (sscanf(token, "%d", &i) != 1)
1912 self_destruct();
1913
1914 if (i < 0)
1915 i = 0;
1916
1917 u = xcalloc(1, sizeof(ushortlist));
1918
1919 u->i = (u_short) i;
1920
1921 for (U = P; *U; U = &(*U)->next)
1922
1923 ;
1924 *U = u;
090089c4 1925 }
270b86af 1926}
090089c4 1927
0153d498 1928static void
a47b9029 1929free_ushortlist(ushortlist ** P)
0153d498 1930{
a47b9029 1931 ushortlist *u;
62e76326 1932
79d39a72 1933 while ((u = *P) != NULL) {
62e76326 1934 *P = u->next;
1935 xfree(u);
a47b9029 1936 }
0153d498 1937}
62e76326 1938
7e3ce7b9 1939#endif
0153d498 1940
270b86af 1941static void
a7d59104 1942dump_int(StoreEntry * entry, const char *name, int var)
270b86af 1943{
f53b06f9 1944 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 1945}
c1c29eb6 1946
94439e4e 1947void
270b86af 1948parse_int(int *var)
1949{
270b86af 1950 int i;
0e4e0e7d 1951 i = GetInteger();
270b86af 1952 *var = i;
1953}
090089c4 1954
0153d498 1955static void
1956free_int(int *var)
1957{
a47b9029 1958 *var = 0;
0153d498 1959}
1960
270b86af 1961static void
a7d59104 1962dump_onoff(StoreEntry * entry, const char *name, int var)
270b86af 1963{
f53b06f9 1964 storeAppendPrintf(entry, "%s %s\n", name, var ? "on" : "off");
270b86af 1965}
090089c4 1966
d205783b 1967void
270b86af 1968parse_onoff(int *var)
1969{
1970 char *token = strtok(NULL, w_space);
090089c4 1971
270b86af 1972 if (token == NULL)
62e76326 1973 self_destruct();
1974
270b86af 1975 if (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))
62e76326 1976 *var = 1;
270b86af 1977 else
62e76326 1978 *var = 0;
270b86af 1979}
e90100aa 1980
0153d498 1981#define free_onoff free_int
52d3f198 1982
1983static void
1984dump_tristate(StoreEntry * entry, const char *name, int var)
1985{
1986 const char *state;
1987
1988 if (var > 0)
1989 state = "on";
1990 else if (var < 0)
1991 state = "warn";
1992 else
1993 state = "off";
1994
1995 storeAppendPrintf(entry, "%s %s\n", name, state);
1996}
1997
1998static void
1999parse_tristate(int *var)
2000{
2001 char *token = strtok(NULL, w_space);
2002
2003 if (token == NULL)
2004 self_destruct();
2005
2006 if (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))
2007 *var = 1;
2008 else if (!strcasecmp(token, "warn"))
2009 *var = -1;
2010 else
2011 *var = 0;
2012}
2013
2014#define free_tristate free_int
30a4f2a8 2015
270b86af 2016static void
a7d59104 2017dump_refreshpattern(StoreEntry * entry, const char *name, refresh_t * head)
270b86af 2018{
d41de3c1 2019 while (head != NULL) {
62e76326 2020 storeAppendPrintf(entry, "%s%s %s %d %d%% %d\n",
2021 name,
2022 head->flags.icase ? " -i" : null_string,
2023 head->pattern,
2024 (int) head->min / 60,
2025 (int) (100.0 * head->pct + 0.5),
2026 (int) head->max / 60);
4c3ef9b2 2027
2028 if (head->flags.refresh_ims)
2029 storeAppendPrintf(entry, " refresh-ims");
2030
9f60cfdf 2031#if HTTP_VIOLATIONS
62e76326 2032
2033 if (head->flags.override_expire)
2034 storeAppendPrintf(entry, " override-expire");
2035
2036 if (head->flags.override_lastmod)
2037 storeAppendPrintf(entry, " override-lastmod");
2038
2039 if (head->flags.reload_into_ims)
2040 storeAppendPrintf(entry, " reload-into-ims");
2041
2042 if (head->flags.ignore_reload)
2043 storeAppendPrintf(entry, " ignore-reload");
2044
38f9c547 2045 if (head->flags.ignore_no_cache)
2046 storeAppendPrintf(entry, " ignore-no-cache");
2047
2048 if (head->flags.ignore_no_store)
2049 storeAppendPrintf(entry, " ignore-no-store");
2050
2051 if (head->flags.ignore_private)
2052 storeAppendPrintf(entry, " ignore-private");
2053
2054 if (head->flags.ignore_auth)
2055 storeAppendPrintf(entry, " ignore-auth");
2056
9f60cfdf 2057#endif
62e76326 2058
2059 storeAppendPrintf(entry, "\n");
2060
2061 head = head->next;
d41de3c1 2062 }
270b86af 2063}
090089c4 2064
270b86af 2065static void
f1dc9b30 2066parse_refreshpattern(refresh_t ** head)
270b86af 2067{
f1dc9b30 2068 char *token;
2069 char *pattern;
2070 time_t min = 0;
c3f6d204 2071 double pct = 0.0;
f1dc9b30 2072 time_t max = 0;
4c3ef9b2 2073 int refresh_ims = 0;
9f60cfdf 2074#if HTTP_VIOLATIONS
62e76326 2075
1dfa1d81 2076 int override_expire = 0;
2077 int override_lastmod = 0;
cbe3a719 2078 int reload_into_ims = 0;
2079 int ignore_reload = 0;
38f9c547 2080 int ignore_no_cache = 0;
2081 int ignore_no_store = 0;
2082 int ignore_private = 0;
2083 int ignore_auth = 0;
9f60cfdf 2084#endif
62e76326 2085
f1dc9b30 2086 int i;
2087 refresh_t *t;
2088 regex_t comp;
2089 int errcode;
2090 int flags = REG_EXTENDED | REG_NOSUB;
62e76326 2091
f1dc9b30 2092 if ((token = strtok(NULL, w_space)) == NULL)
62e76326 2093 self_destruct();
2094
f1dc9b30 2095 if (strcmp(token, "-i") == 0) {
62e76326 2096 flags |= REG_ICASE;
2097 token = strtok(NULL, w_space);
f1dc9b30 2098 } else if (strcmp(token, "+i") == 0) {
62e76326 2099 flags &= ~REG_ICASE;
2100 token = strtok(NULL, w_space);
f1dc9b30 2101 }
62e76326 2102
f1dc9b30 2103 if (token == NULL)
62e76326 2104 self_destruct();
2105
f1dc9b30 2106 pattern = xstrdup(token);
62e76326 2107
0e4e0e7d 2108 i = GetInteger(); /* token: min */
62e76326 2109
f1dc9b30 2110 min = (time_t) (i * 60); /* convert minutes to seconds */
62e76326 2111
0e4e0e7d 2112 i = GetInteger(); /* token: pct */
62e76326 2113
c3f6d204 2114 pct = (double) i / 100.0;
62e76326 2115
0e4e0e7d 2116 i = GetInteger(); /* token: max */
62e76326 2117
f1dc9b30 2118 max = (time_t) (i * 60); /* convert minutes to seconds */
62e76326 2119
1dfa1d81 2120 /* Options */
2121 while ((token = strtok(NULL, w_space)) != NULL) {
4c3ef9b2 2122 if (!strcmp(token, "refresh-ims")) {
2123 refresh_ims = 1;
9f60cfdf 2124#if HTTP_VIOLATIONS
62e76326 2125
4c3ef9b2 2126 } else if (!strcmp(token, "override-expire"))
62e76326 2127 override_expire = 1;
2128 else if (!strcmp(token, "override-lastmod"))
2129 override_lastmod = 1;
38f9c547 2130 else if (!strcmp(token, "ignore-no-cache"))
2131 ignore_no_cache = 1;
2132 else if (!strcmp(token, "ignore-no-store"))
2133 ignore_no_store = 1;
2134 else if (!strcmp(token, "ignore-private"))
2135 ignore_private = 1;
2136 else if (!strcmp(token, "ignore-auth"))
2137 ignore_auth = 1;
62e76326 2138 else if (!strcmp(token, "reload-into-ims")) {
2139 reload_into_ims = 1;
2140 refresh_nocache_hack = 1;
2141 /* tell client_side.c that this is used */
2142 } else if (!strcmp(token, "ignore-reload")) {
2143 ignore_reload = 1;
2144 refresh_nocache_hack = 1;
2145 /* tell client_side.c that this is used */
9f60cfdf 2146#endif
62e76326 2147
4c3ef9b2 2148 } else
62e76326 2149 debug(22, 0) ("redreshAddToList: Unknown option '%s': %s\n",
2150 pattern, token);
1dfa1d81 2151 }
62e76326 2152
f1dc9b30 2153 if ((errcode = regcomp(&comp, pattern, flags)) != 0) {
62e76326 2154 char errbuf[256];
2155 regerror(errcode, &comp, errbuf, sizeof errbuf);
2156 debug(22, 0) ("%s line %d: %s\n",
2157 cfg_filename, config_lineno, config_input_line);
2158 debug(22, 0) ("refreshAddToList: Invalid regular expression '%s': %s\n",
2159 pattern, errbuf);
2160 return;
f1dc9b30 2161 }
62e76326 2162
c3f6d204 2163 pct = pct < 0.0 ? 0.0 : pct;
f1dc9b30 2164 max = max < 0 ? 0 : max;
e6ccf245 2165 t = static_cast<refresh_t *>(xcalloc(1, sizeof(refresh_t)));
f1dc9b30 2166 t->pattern = (char *) xstrdup(pattern);
2167 t->compiled_pattern = comp;
2168 t->min = min;
c3f6d204 2169 t->pct = pct;
f1dc9b30 2170 t->max = max;
62e76326 2171
c3f6d204 2172 if (flags & REG_ICASE)
62e76326 2173 t->flags.icase = 1;
2174
4c3ef9b2 2175 if (refresh_ims)
2176 t->flags.refresh_ims = 1;
2177
9f60cfdf 2178#if HTTP_VIOLATIONS
62e76326 2179
1dfa1d81 2180 if (override_expire)
62e76326 2181 t->flags.override_expire = 1;
2182
1dfa1d81 2183 if (override_lastmod)
62e76326 2184 t->flags.override_lastmod = 1;
2185
cbe3a719 2186 if (reload_into_ims)
62e76326 2187 t->flags.reload_into_ims = 1;
2188
cbe3a719 2189 if (ignore_reload)
62e76326 2190 t->flags.ignore_reload = 1;
2191
38f9c547 2192 if (ignore_no_cache)
2193 t->flags.ignore_no_cache = 1;
2194
2195 if (ignore_no_store)
2196 t->flags.ignore_no_store = 1;
2197
2198 if (ignore_private)
2199 t->flags.ignore_private = 1;
2200
2201 if (ignore_auth)
2202 t->flags.ignore_auth = 1;
2203
9f60cfdf 2204#endif
62e76326 2205
f1dc9b30 2206 t->next = NULL;
62e76326 2207
f1dc9b30 2208 while (*head)
62e76326 2209 head = &(*head)->next;
2210
f1dc9b30 2211 *head = t;
62e76326 2212
f1dc9b30 2213 safe_free(pattern);
270b86af 2214}
090089c4 2215
8e89beb3 2216#if UNUSED_CODE
6b53c392 2217static int
a4b8110e 2218check_null_refreshpattern(refresh_t * data)
6b53c392 2219{
80e073c0 2220 return data == NULL;
6b53c392 2221}
62e76326 2222
8e89beb3 2223#endif
6b53c392 2224
270b86af 2225static void
a47b9029 2226free_refreshpattern(refresh_t ** head)
270b86af 2227{
f1dc9b30 2228 refresh_t *t;
62e76326 2229
79d39a72 2230 while ((t = *head) != NULL) {
62e76326 2231 *head = t->next;
2232 safe_free(t->pattern);
2233 regfree(&t->compiled_pattern);
2234 safe_free(t);
f1dc9b30 2235 }
c2066637 2236
8970d351 2237#if HTTP_VIOLATIONS
c2066637 2238 refresh_nocache_hack = 0;
8970d351 2239
2240#endif
270b86af 2241}
12b9e9b1 2242
270b86af 2243static void
a7d59104 2244dump_string(StoreEntry * entry, const char *name, char *var)
270b86af 2245{
f53b06f9 2246 if (var != NULL)
62e76326 2247 storeAppendPrintf(entry, "%s %s\n", name, var);
270b86af 2248}
98ffb7e4 2249
270b86af 2250static void
0153d498 2251parse_string(char **var)
270b86af 2252{
2253 char *token = strtok(NULL, w_space);
270b86af 2254 safe_free(*var);
62e76326 2255
270b86af 2256 if (token == NULL)
62e76326 2257 self_destruct();
2258
270b86af 2259 *var = xstrdup(token);
2260}
b15e6857 2261
3a69ddf3 2262void
2263ConfigParser::ParseString(char **var)
2264{
2265 parse_string(var);
2266}
2267
2268void
2269ConfigParser::ParseString(String *var)
2270{
2271 char *token = strtok(NULL, w_space);
2272
2273 if (token == NULL)
2274 self_destruct();
2275
2276 var->reset(token);
2277}
2278
0153d498 2279static void
2280free_string(char **var)
2281{
027acbaf 2282 safe_free(*var);
0153d498 2283}
caebbe00 2284
94439e4e 2285void
f1dc9b30 2286parse_eol(char *volatile *var)
270b86af 2287{
852751f7 2288 unsigned char *token = (unsigned char *) strtok(NULL, null_string);
270b86af 2289 safe_free(*var);
62e76326 2290
f1dc9b30 2291 if (token == NULL)
62e76326 2292 self_destruct();
2293
2d72d4fd 2294 while (*token && isspace(*token))
62e76326 2295 token++;
2296
20cb98c9 2297 if (!*token)
62e76326 2298 self_destruct();
2299
852751f7 2300 *var = xstrdup((char *) token);
270b86af 2301}
090089c4 2302
52d3f198 2303#define dump_eol dump_string
2304#define free_eol free_string
2305
d9e04dc7 2306void
2307parse_debug(char *volatile *var)
2308{
2309 parse_eol(var);
2310 safe_free(debug_options)
2311 debug_options = xstrdup(Config.debugOptions);
2312 Debug::parseOptions(Config.debugOptions);
2313}
2314
52d3f198 2315#define dump_debug dump_string
2316#define free_debug free_string
2317
270b86af 2318static void
a7d59104 2319dump_time_t(StoreEntry * entry, const char *name, time_t var)
090089c4 2320{
f53b06f9 2321 storeAppendPrintf(entry, "%s %d seconds\n", name, (int) var);
090089c4 2322}
2323
94439e4e 2324void
a47b9029 2325parse_time_t(time_t * var)
0ffd22bc 2326{
f1dc9b30 2327 parseTimeLine(var, T_SECOND_STR);
0ffd22bc 2328}
2329
270b86af 2330static void
a47b9029 2331free_time_t(time_t * var)
270b86af 2332{
a47b9029 2333 *var = 0;
270b86af 2334}
9906e724 2335
2336static void
a7d59104 2337dump_size_t(StoreEntry * entry, const char *name, size_t var)
1b635117 2338{
f53b06f9 2339 storeAppendPrintf(entry, "%s %d\n", name, (int) var);
1b635117 2340}
2341
2342static void
a7d59104 2343dump_b_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 2344{
f53b06f9 2345 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
9906e724 2346}
2347
2348static void
a7d59104 2349dump_kb_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 2350{
f53b06f9 2351 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_KBYTES_STR);
9906e724 2352}
2353
2354static void
a47b9029 2355parse_size_t(size_t * var)
1b635117 2356{
1b635117 2357 int i;
0e4e0e7d 2358 i = GetInteger();
1b635117 2359 *var = (size_t) i;
2360}
2361
2362static void
2363parse_b_size_t(size_t * var)
9906e724 2364{
2365 parseBytesLine(var, B_BYTES_STR);
2366}
2367
2368static void
a47b9029 2369parse_kb_size_t(size_t * var)
9906e724 2370{
2371 parseBytesLine(var, B_KBYTES_STR);
2372}
2373
2374static void
a47b9029 2375free_size_t(size_t * var)
9906e724 2376{
a47b9029 2377 *var = 0;
9906e724 2378}
2379
1b635117 2380#define free_b_size_t free_size_t
9906e724 2381#define free_kb_size_t free_size_t
2382#define free_mb_size_t free_size_t
2383#define free_gb_size_t free_size_t
090089c4 2384
8203a132 2385static void
a7d59104 2386dump_ushort(StoreEntry * entry, const char *name, u_short var)
090089c4 2387{
f53b06f9 2388 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 2389}
090089c4 2390
0153d498 2391static void
a47b9029 2392free_ushort(u_short * u)
0153d498 2393{
2394 *u = 0;
2395}
2396
270b86af 2397static void
2398parse_ushort(u_short * var)
b67e2c8c 2399{
2400 ConfigParser::ParseUShort(var);
2401}
2402
2403void
2404ConfigParser::ParseUShort(u_short *var)
270b86af 2405{
270b86af 2406 int i;
090089c4 2407
0e4e0e7d 2408 i = GetInteger();
62e76326 2409
270b86af 2410 if (i < 0)
62e76326 2411 i = 0;
2412
270b86af 2413 *var = (u_short) i;
090089c4 2414}
2415
3a69ddf3 2416void
2417ConfigParser::ParseBool(bool *var)
2418{
2419 int i = GetInteger();
2420
2421 if (0 == i)
2422 *var = false;
2423 else if (1 == i)
2424 *var = true;
2425 else
2426 self_destruct();
2427}
2428
270b86af 2429static void
a7d59104 2430dump_wordlist(StoreEntry * entry, const char *name, wordlist * list)
270b86af 2431{
270b86af 2432 while (list != NULL) {
62e76326 2433 storeAppendPrintf(entry, "%s %s\n", name, list->key);
2434 list = list->next;
429fdbec 2435 }
429fdbec 2436}
2437
3a69ddf3 2438void
2439ConfigParser::ParseWordList(wordlist ** list)
2440{
2441 parse_wordlist(list);
2442}
2443
94439e4e 2444void
270b86af 2445parse_wordlist(wordlist ** list)
429fdbec 2446{
270b86af 2447 char *token;
a3c6890f 2448 char *t = strtok(NULL, "");
62e76326 2449
a3c6890f 2450 while ((token = strwordtok(NULL, &t)))
62e76326 2451 wordlistAdd(list, token);
429fdbec 2452}
270b86af 2453
f8d9f54a 2454static int
5da06f20 2455check_null_wordlist(wordlist * w)
f8d9f54a 2456{
2457 return w == NULL;
2458}
2459
63e9d884 2460static int
c6d5b87b 2461check_null_acl_access(acl_access * a)
63e9d884 2462{
2463 return a == NULL;
2464}
2465
0153d498 2466#define free_wordlist wordlistDestroy
270b86af 2467
d548ee64 2468#define free_uri_whitespace free_int
2469
2470static void
2471parse_uri_whitespace(int *var)
2472{
2473 char *token = strtok(NULL, w_space);
62e76326 2474
d548ee64 2475 if (token == NULL)
62e76326 2476 self_destruct();
2477
7e3ce7b9 2478 if (!strcasecmp(token, "strip"))
62e76326 2479 *var = URI_WHITESPACE_STRIP;
7e3ce7b9 2480 else if (!strcasecmp(token, "deny"))
62e76326 2481 *var = URI_WHITESPACE_DENY;
d548ee64 2482 else if (!strcasecmp(token, "allow"))
62e76326 2483 *var = URI_WHITESPACE_ALLOW;
d548ee64 2484 else if (!strcasecmp(token, "encode"))
62e76326 2485 *var = URI_WHITESPACE_ENCODE;
d548ee64 2486 else if (!strcasecmp(token, "chop"))
62e76326 2487 *var = URI_WHITESPACE_CHOP;
d548ee64 2488 else
62e76326 2489 self_destruct();
d548ee64 2490}
2491
d548ee64 2492static void
2493dump_uri_whitespace(StoreEntry * entry, const char *name, int var)
2494{
c193c972 2495 const char *s;
62e76326 2496
d548ee64 2497 if (var == URI_WHITESPACE_ALLOW)
62e76326 2498 s = "allow";
d548ee64 2499 else if (var == URI_WHITESPACE_ENCODE)
62e76326 2500 s = "encode";
d548ee64 2501 else if (var == URI_WHITESPACE_CHOP)
62e76326 2502 s = "chop";
7e3ce7b9 2503 else if (var == URI_WHITESPACE_DENY)
62e76326 2504 s = "deny";
7e3ce7b9 2505 else
62e76326 2506 s = "strip";
2507
d548ee64 2508 storeAppendPrintf(entry, "%s %s\n", name, s);
2509}
2510
6a566b9c 2511static void
c1dd71ae 2512free_removalpolicy(RemovalPolicySettings ** settings)
6a566b9c 2513{
2514 if (!*settings)
62e76326 2515 return;
2516
6a566b9c 2517 free_string(&(*settings)->type);
62e76326 2518
6a566b9c 2519 free_wordlist(&(*settings)->args);
62e76326 2520
c8f4eac4 2521 delete *settings;
62e76326 2522
6a566b9c 2523 *settings = NULL;
2524}
2525
2526static void
c1dd71ae 2527parse_removalpolicy(RemovalPolicySettings ** settings)
6a566b9c 2528{
2529 if (*settings)
62e76326 2530 free_removalpolicy(settings);
2531
c8f4eac4 2532 *settings = new RemovalPolicySettings;
62e76326 2533
6a566b9c 2534 parse_string(&(*settings)->type);
62e76326 2535
6a566b9c 2536 parse_wordlist(&(*settings)->args);
2537}
2538
2539static void
c1dd71ae 2540dump_removalpolicy(StoreEntry * entry, const char *name, RemovalPolicySettings * settings)
6a566b9c 2541{
2542 wordlist *args;
2543 storeAppendPrintf(entry, "%s %s", name, settings->type);
2544 args = settings->args;
62e76326 2545
6a566b9c 2546 while (args) {
62e76326 2547 storeAppendPrintf(entry, " %s", args->key);
2548 args = args->next;
6a566b9c 2549 }
62e76326 2550
be58afb5 2551 storeAppendPrintf(entry, "\n");
6a566b9c 2552}
c1dd71ae 2553
1ee67578 2554#include "cf_parser.h"
f1dc9b30 2555
2556peer_t
2557parseNeighborType(const char *s)
2558{
2559 if (!strcasecmp(s, "parent"))
62e76326 2560 return PEER_PARENT;
2561
f1dc9b30 2562 if (!strcasecmp(s, "neighbor"))
62e76326 2563 return PEER_SIBLING;
2564
f1dc9b30 2565 if (!strcasecmp(s, "neighbour"))
62e76326 2566 return PEER_SIBLING;
2567
f1dc9b30 2568 if (!strcasecmp(s, "sibling"))
62e76326 2569 return PEER_SIBLING;
2570
f1dc9b30 2571 if (!strcasecmp(s, "multicast"))
62e76326 2572 return PEER_MULTICAST;
2573
f1dc9b30 2574 debug(15, 0) ("WARNING: Unknown neighbor type: %s\n", s);
62e76326 2575
f1dc9b30 2576 return PEER_SIBLING;
2577}
f150dd4b 2578
3f38a55e 2579#if CURRENTLY_UNUSED
2580/* This code was previously used by http_port. Left as it really should
2581 * be used by icp_port and htcp_port
2582 */
52f772de 2583void
2584parse_sockaddr_in_list_token(sockaddr_in_list ** head, char *token)
7e3ce7b9 2585{
7e3ce7b9 2586 char *t;
efd900cb 2587 char *host;
62e76326 2588
7e3ce7b9 2589 const struct hostent *hp;
efd900cb 2590 unsigned short port;
7e3ce7b9 2591 sockaddr_in_list *s;
52f772de 2592
2593 host = NULL;
2594 port = 0;
62e76326 2595
52f772de 2596 if ((t = strchr(token, ':'))) {
62e76326 2597 /* host:port */
2598 host = token;
2599 *t = '\0';
2600 port = (unsigned short) xatoi(t + 1);
2601
2602 if (0 == port)
2603 self_destruct();
5c20d6fa 2604 } else if ((port = xatoi(token)) > 0) {
62e76326 2605 /* port */
52f772de 2606 } else {
62e76326 2607 self_destruct();
52f772de 2608 }
62e76326 2609
e6ccf245 2610 s = static_cast<sockaddr_in_list *>(xcalloc(1, sizeof(*s)));
52f772de 2611 s->s.sin_port = htons(port);
62e76326 2612
52f772de 2613 if (NULL == host)
62e76326 2614 s->s.sin_addr = any_addr;
52f772de 2615 else if (1 == safe_inet_addr(host, &s->s.sin_addr))
62e76326 2616 (void) 0;
52f772de 2617 else if ((hp = gethostbyname(host))) /* dont use ipcache */
62e76326 2618 s->s.sin_addr = inaddrFromHostent(hp);
52f772de 2619 else
62e76326 2620 self_destruct();
2621
52f772de 2622 while (*head)
62e76326 2623 head = &(*head)->next;
2624
52f772de 2625 *head = s;
2626}
2627
2628static void
2629parse_sockaddr_in_list(sockaddr_in_list ** head)
2630{
2631 char *token;
62e76326 2632
52f772de 2633 while ((token = strtok(NULL, w_space))) {
62e76326 2634 parse_sockaddr_in_list_token(head, token);
7e3ce7b9 2635 }
2636}
2637
2638static void
2639dump_sockaddr_in_list(StoreEntry * e, const char *n, const sockaddr_in_list * s)
2640{
2641 while (s) {
62e76326 2642 storeAppendPrintf(e, "%s %s:%d\n",
2643 n,
2644 inet_ntoa(s->s.sin_addr),
2645 ntohs(s->s.sin_port));
2646 s = s->next;
7e3ce7b9 2647 }
2648}
2649
2650static void
2651free_sockaddr_in_list(sockaddr_in_list ** head)
2652{
2653 sockaddr_in_list *s;
62e76326 2654
7e3ce7b9 2655 while ((s = *head) != NULL) {
62e76326 2656 *head = s->next;
2657 xfree(s);
7e3ce7b9 2658 }
2659}
2660
2661static int
2662check_null_sockaddr_in_list(const sockaddr_in_list * s)
2663{
2664 return NULL == s;
2665}
62e76326 2666
3f38a55e 2667#endif /* CURRENTLY_UNUSED */
7e3ce7b9 2668
d193a436 2669static void
3f38a55e 2670parse_http_port_specification(http_port_list * s, char *token)
d193a436 2671{
3f38a55e 2672 char *host = NULL;
62e76326 2673
d193a436 2674 const struct hostent *hp;
3f38a55e 2675 unsigned short port = 0;
2676 char *t;
62e76326 2677
5529ca8a 2678 s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
2679
d193a436 2680 if ((t = strchr(token, ':'))) {
62e76326 2681 /* host:port */
2682 host = token;
2683 *t = '\0';
2684 port = (unsigned short) atoi(t + 1);
2685
2686 if (0 == port)
2687 self_destruct();
3f38a55e 2688 } else if ((port = atoi(token)) > 0) {
62e76326 2689 /* port */
d193a436 2690 } else {
62e76326 2691 self_destruct();
d193a436 2692 }
62e76326 2693
d193a436 2694 s->s.sin_port = htons(port);
62e76326 2695
d193a436 2696 if (NULL == host)
62e76326 2697 s->s.sin_addr = any_addr;
d193a436 2698 else if (1 == safe_inet_addr(host, &s->s.sin_addr))
62e76326 2699 (void) 0;
3f38a55e 2700 else if ((hp = gethostbyname(host))) {
62e76326 2701 /* dont use ipcache */
2702 s->s.sin_addr = inaddrFromHostent(hp);
2703 s->defaultsite = xstrdup(host);
3f38a55e 2704 } else
62e76326 2705 self_destruct();
3f38a55e 2706}
2707
2708static void
2709parse_http_port_option(http_port_list * s, char *token)
2710{
2711 if (strncmp(token, "defaultsite=", 12) == 0) {
62e76326 2712 safe_free(s->defaultsite);
2713 s->defaultsite = xstrdup(token + 12);
2714 s->accel = 1;
3f38a55e 2715 } else if (strncmp(token, "name=", 5) == 0) {
62e76326 2716 safe_free(s->name);
2717 s->name = xstrdup(token + 5);
3f38a55e 2718 } else if (strcmp(token, "transparent") == 0) {
62e76326 2719 s->transparent = 1;
3f38a55e 2720 } else if (strcmp(token, "vhost") == 0) {
62e76326 2721 s->vhost = 1;
2722 s->accel = 1;
3f38a55e 2723 } else if (strcmp(token, "vport") == 0) {
62e76326 2724 s->vport = -1;
2725 s->accel = 1;
3f38a55e 2726 } else if (strncmp(token, "vport=", 6) == 0) {
62e76326 2727 s->vport = atoi(token + 6);
2728 s->accel = 1;
3f38a55e 2729 } else if (strncmp(token, "protocol=", 9) == 0) {
62e76326 2730 s->protocol = xstrdup(token + 9);
2731 s->accel = 1;
3f38a55e 2732 } else if (strcmp(token, "accel") == 0) {
62e76326 2733 s->accel = 1;
5529ca8a 2734 } else if (strncmp(token, "disable-pmtu-discovery=", 23) == 0) {
2735 if (!strcasecmp(token + 23, "off"))
2736 s->disable_pmtu_discovery = DISABLE_PMTU_OFF;
2737 else if (!strcasecmp(token + 23, "transparent"))
2738 s->disable_pmtu_discovery = DISABLE_PMTU_TRANSPARENT;
2739 else if (!strcasecmp(token + 23, "always"))
2740 s->disable_pmtu_discovery = DISABLE_PMTU_ALWAYS;
2741 else
2742 self_destruct();
3f38a55e 2743 } else {
62e76326 2744 self_destruct();
3f38a55e 2745 }
2746}
2747
2748static void
2749free_generic_http_port_data(http_port_list * s)
2750{
2751 safe_free(s->name);
2752 safe_free(s->defaultsite);
f9ad0106 2753 safe_free(s->protocol);
3f38a55e 2754}
2755
2756static void
2757cbdataFree_http_port(void *data)
2758{
2759 free_generic_http_port_data((http_port_list *)data);
2760}
2761
3f38a55e 2762static http_port_list *
2763create_http_port(char *portspec)
2764{
2765 CBDATA_TYPE(http_port_list);
2766 CBDATA_INIT_TYPE_FREECB(http_port_list, cbdataFree_http_port);
2767
2768 http_port_list *s = cbdataAlloc(http_port_list);
2769 s->protocol = xstrdup("http");
2770 parse_http_port_specification(s, portspec);
2771 return s;
2772}
2773
2774void
2775add_http_port(char *portspec)
2776{
2777 http_port_list *s = create_http_port(portspec);
2778 s->next = Config.Sockaddr.http;
2779 Config.Sockaddr.http = s;
2780}
2781
2782static void
2783parse_http_port_list(http_port_list ** head)
2784{
2785 char *token = strtok(NULL, w_space);
62e76326 2786
3f38a55e 2787 if (!token)
62e76326 2788 self_destruct();
2789
3f38a55e 2790 http_port_list *s = create_http_port(token);
62e76326 2791
3f38a55e 2792 /* parse options ... */
2793 while ((token = strtok(NULL, w_space))) {
62e76326 2794 parse_http_port_option(s, token);
3f38a55e 2795 }
62e76326 2796
3f38a55e 2797 while (*head)
62e76326 2798 head = &(*head)->next;
2799
3f38a55e 2800 *head = s;
2801}
2802
2803static void
2804dump_generic_http_port(StoreEntry * e, const char *n, const http_port_list * s)
2805{
2806 storeAppendPrintf(e, "%s %s:%d",
62e76326 2807 n,
2808 inet_ntoa(s->s.sin_addr),
2809 ntohs(s->s.sin_port));
2810
3f38a55e 2811 if (s->defaultsite)
62e76326 2812 storeAppendPrintf(e, " defaultsite=%s", s->defaultsite);
2813
3f38a55e 2814 if (s->transparent)
62e76326 2815 storeAppendPrintf(e, " transparent");
2816
3f38a55e 2817 if (s->vhost)
62e76326 2818 storeAppendPrintf(e, " vhost");
2819
3f38a55e 2820 if (s->vport)
62e76326 2821 storeAppendPrintf(e, " vport");
5529ca8a 2822
2823 if (s->disable_pmtu_discovery != DISABLE_PMTU_OFF) {
2824 const char *pmtu;
2825
2826 if (s->disable_pmtu_discovery == DISABLE_PMTU_ALWAYS)
2827 pmtu = "always";
2828 else
2829 pmtu = "transparent";
2830
2831 storeAppendPrintf(e, " disable-pmtu-discovery=%s", pmtu);
2832 }
3f38a55e 2833}
62e76326 2834
3f38a55e 2835static void
2836dump_http_port_list(StoreEntry * e, const char *n, const http_port_list * s)
2837{
2838 while (s) {
62e76326 2839 dump_generic_http_port(e, n, s);
2840 storeAppendPrintf(e, "\n");
2841 s = s->next;
3f38a55e 2842 }
2843}
2844
2845static void
2846free_http_port_list(http_port_list ** head)
2847{
2848 http_port_list *s;
62e76326 2849
3f38a55e 2850 while ((s = *head) != NULL) {
62e76326 2851 *head = s->next;
2852 cbdataFree(s);
3f38a55e 2853 }
2854}
2855
2856#if UNUSED_CODE
2857static int
2858check_null_http_port_list(const http_port_list * s)
2859{
2860 return NULL == s;
2861}
62e76326 2862
3f38a55e 2863#endif
2864
2865#if USE_SSL
2866static void
2867cbdataFree_https_port(void *data)
2868{
2869 https_port_list *s = (https_port_list *)data;
2870 free_generic_http_port_data(&s->http);
2871 safe_free(s->cert);
2872 safe_free(s->key);
f9ad0106 2873 safe_free(s->options);
2874 safe_free(s->cipher);
2875 safe_free(s->cafile);
2876 safe_free(s->capath);
2877 safe_free(s->dhfile);
2878 safe_free(s->sslflags);
3f38a55e 2879}
2880
2881static void
2882parse_https_port_list(https_port_list ** head)
2883{
2884 CBDATA_TYPE(https_port_list);
2885 char *token;
2886 https_port_list *s;
2887 CBDATA_INIT_TYPE_FREECB(https_port_list, cbdataFree_https_port);
2888 token = strtok(NULL, w_space);
62e76326 2889
3f38a55e 2890 if (!token)
62e76326 2891 self_destruct();
2892
3f38a55e 2893 s = cbdataAlloc(https_port_list);
62e76326 2894
3f38a55e 2895 s->http.protocol = xstrdup("https");
62e76326 2896
3f38a55e 2897 parse_http_port_specification(&s->http, token);
62e76326 2898
d193a436 2899 /* parse options ... */
2900 while ((token = strtok(NULL, w_space))) {
62e76326 2901 if (strncmp(token, "cert=", 5) == 0) {
2902 safe_free(s->cert);
2903 s->cert = xstrdup(token + 5);
2904 } else if (strncmp(token, "key=", 4) == 0) {
2905 safe_free(s->key);
2906 s->key = xstrdup(token + 4);
2907 } else if (strncmp(token, "version=", 8) == 0) {
2908 s->version = xatoi(token + 8);
8bbd476e 2909
2910 if (s->version < 1 || s->version > 4)
2911 self_destruct();
62e76326 2912 } else if (strncmp(token, "options=", 8) == 0) {
2913 safe_free(s->options);
2914 s->options = xstrdup(token + 8);
2915 } else if (strncmp(token, "cipher=", 7) == 0) {
2916 safe_free(s->cipher);
2917 s->cipher = xstrdup(token + 7);
2918 } else if (strncmp(token, "clientca=", 9) == 0) {
2919 safe_free(s->clientca);
2920 s->clientca = xstrdup(token + 9);
2921 } else if (strncmp(token, "cafile=", 7) == 0) {
2922 safe_free(s->cafile);
2923 s->cafile = xstrdup(token + 7);
2924 } else if (strncmp(token, "capath=", 7) == 0) {
2925 safe_free(s->capath);
2926 s->capath = xstrdup(token + 7);
a82a4fe4 2927 } else if (strncmp(token, "crlfile=", 8) == 0) {
2928 safe_free(s->crlfile);
2929 s->crlfile = xstrdup(token + 8);
35105e4b 2930 } else if (strncmp(token, "dhparams=", 9) == 0) {
2931 safe_free(s->dhfile);
2932 s->dhfile = xstrdup(token + 9);
62e76326 2933 } else if (strncmp(token, "sslflags=", 9) == 0) {
2934 safe_free(s->sslflags);
2935 s->sslflags = xstrdup(token + 9);
6b2936d5 2936 } else if (strncmp(token, "sslcontext=", 11) == 0) {
2937 safe_free(s->sslcontext);
2938 s->sslcontext = xstrdup(token + 11);
62e76326 2939 } else {
2940 parse_http_port_option(&s->http, token);
2941 }
d193a436 2942 }
62e76326 2943
8abf232c 2944 while (*head) {
2945 http_port_list ** headTmp = &(*head)->http.next;
2946 head = (https_port_list **)headTmp;
2947 }
62e76326 2948
d193a436 2949 *head = s;
2950}
2951
2952static void
2953dump_https_port_list(StoreEntry * e, const char *n, const https_port_list * s)
2954{
2955 while (s) {
62e76326 2956 dump_generic_http_port(e, n, &s->http);
2957
2958 if (s->cert)
2959 storeAppendPrintf(e, " cert=%s", s->cert);
2960
2961 if (s->key)
5c83dac8 2962 storeAppendPrintf(e, " key=%s", s->key);
62e76326 2963
2964 if (s->version)
2965 storeAppendPrintf(e, " version=%d", s->version);
2966
2967 if (s->options)
2968 storeAppendPrintf(e, " options=%s", s->options);
2969
2970 if (s->cipher)
2971 storeAppendPrintf(e, " cipher=%s", s->cipher);
2972
2973 if (s->cafile)
2974 storeAppendPrintf(e, " cafile=%s", s->cafile);
2975
2976 if (s->capath)
2977 storeAppendPrintf(e, " capath=%s", s->capath);
2978
a82a4fe4 2979 if (s->crlfile)
2980 storeAppendPrintf(e, " crlfile=%s", s->crlfile);
2981
35105e4b 2982 if (s->dhfile)
2983 storeAppendPrintf(e, " dhparams=%s", s->dhfile);
2984
62e76326 2985 if (s->sslflags)
2986 storeAppendPrintf(e, " sslflags=%s", s->sslflags);
2987
6b2936d5 2988 if (s->sslcontext)
2989 storeAppendPrintf(e, " sslcontext=%s", s->sslcontext);
2990
62e76326 2991 storeAppendPrintf(e, "\n");
2992
2993 s = (https_port_list *) s->http.next;
d193a436 2994 }
2995}
2996
2997static void
2998free_https_port_list(https_port_list ** head)
2999{
3000 https_port_list *s;
62e76326 3001
d193a436 3002 while ((s = *head) != NULL) {
62e76326 3003 *head = (https_port_list *) s->http.next;
3004 cbdataFree(s);
d193a436 3005 }
3006}
3007
3008#if 0
3009static int
3010check_null_https_port_list(const https_port_list * s)
3011{
3012 return NULL == s;
3013}
62e76326 3014
d193a436 3015#endif
3016
3017#endif /* USE_SSL */
3018
f150dd4b 3019void
3020configFreeMemory(void)
3021{
23ff6968 3022 free_all();
f150dd4b 3023}
f0b19334 3024
94439e4e 3025void
f0b19334 3026requirePathnameExists(const char *name, const char *path)
3027{
62e76326 3028
f0b19334 3029 struct stat sb;
08577e16 3030 char pathbuf[BUFSIZ];
f0b19334 3031 assert(path != NULL);
62e76326 3032
0b796acd 3033 if (Config.chroot_dir && (geteuid() == 0)) {
62e76326 3034 snprintf(pathbuf, BUFSIZ, "%s/%s", Config.chroot_dir, path);
3035 path = pathbuf;
08577e16 3036 }
62e76326 3037
a572d8be 3038 if (stat(path, &sb) < 0) {
3039 if (opt_send_signal == -1 || opt_send_signal == SIGHUP)
3040 fatalf("%s %s: %s", name, path, xstrerror());
3041 else
3042 fprintf(stderr, "WARNING: %s %s: %s\n", name, path, xstrerror());
3043 }
f0b19334 3044}
d860a1aa 3045
3046char *
3047strtokFile(void)
3048{
d295d770 3049 return ConfigParser::strtokFile();
d860a1aa 3050}
7684c4b1 3051
450e0c10 3052#include "AccessLogEntry.h"
3053/* TODO: split out parsing somehow ...*/
7684c4b1 3054static void
3055parse_logformat(logformat ** logformat_definitions)
3056{
3057 logformat *nlf;
3058 char *name, *def;
3059
3060 if ((name = strtok(NULL, w_space)) == NULL)
3061 self_destruct();
3062
3063 if ((def = strtok(NULL, "\r\n")) == NULL)
3064 self_destruct();
3065
944113fe 3066 debug(3, 2) ("Logformat for '%s' is '%s'\n", name, def);
7684c4b1 3067
3068 nlf = (logformat *)xcalloc(1, sizeof(logformat));
3069
3070 nlf->name = xstrdup(name);
3071
3072 if (!accessLogParseLogFormat(&nlf->format, def))
3073 self_destruct();
3074
3075 nlf->next = *logformat_definitions;
3076
3077 *logformat_definitions = nlf;
3078}
3079
3080static void
3081parse_access_log(customlog ** logs)
3082{
3083 const char *filename, *logdef_name;
3084 customlog *cl;
3085 logformat *lf;
3086
3087 cl = (customlog *)xcalloc(1, sizeof(*cl));
3088
3089 if ((filename = strtok(NULL, w_space)) == NULL)
3090 self_destruct();
3091
3092 if (strcmp(filename, "none") == 0) {
3093 cl->type = CLF_NONE;
3094 goto done;
3095 }
3096
3097 if ((logdef_name = strtok(NULL, w_space)) == NULL)
3098 logdef_name = "auto";
3099
3100 debug(3, 9) ("Log definition name '%s' file '%s'\n", logdef_name, filename);
3101
3102 cl->filename = xstrdup(filename);
3103
3104 /* look for the definition pointer corresponding to this name */
3105 lf = Config.Log.logformats;
3106
3107 while (lf != NULL) {
3108 debug(3, 9) ("Comparing against '%s'\n", lf->name);
3109
3110 if (strcmp(lf->name, logdef_name) == 0)
3111 break;
3112
3113 lf = lf->next;
3114 }
3115
3116 if (lf != NULL) {
3117 cl->type = CLF_CUSTOM;
3118 cl->logFormat = lf;
3119 } else if (strcmp(logdef_name, "auto") == 0) {
3120 cl->type = CLF_AUTO;
3121 } else if (strcmp(logdef_name, "squid") == 0) {
3122 cl->type = CLF_SQUID;
3123 } else if (strcmp(logdef_name, "common") == 0) {
3124 cl->type = CLF_COMMON;
3125 } else {
3126 debug(3, 0) ("Log format '%s' is not defined\n", logdef_name);
3127 self_destruct();
3128 }
3129
3130done:
a9f20260 3131 aclParseAclList(LegacyParser, &cl->aclList);
7684c4b1 3132
3133 while (*logs)
3134 logs = &(*logs)->next;
3135
3136 *logs = cl;
3137}
3138
d64bef4c 3139static int
3140check_null_access_log(customlog *customlog_definitions)
3141{
3142 return customlog_definitions == NULL;
3143}
3144
7684c4b1 3145static void
3146dump_logformat(StoreEntry * entry, const char *name, logformat * definitions)
3147{
3148 accessLogDumpLogFormat(entry, name, definitions);
3149}
3150
3151static void
3152dump_access_log(StoreEntry * entry, const char *name, customlog * logs)
3153{
3154 customlog *log;
3155
3156 for (log = logs; log; log = log->next) {
3157 storeAppendPrintf(entry, "%s ", name);
3158
3159 switch (log->type) {
3160
3161 case CLF_CUSTOM:
3162 storeAppendPrintf(entry, "%s %s", log->filename, log->logFormat->name);
3163 break;
3164
3165 case CLF_NONE:
3166 storeAppendPrintf(entry, "none");
3167 break;
3168
3169 case CLF_SQUID:
3170 storeAppendPrintf(entry, "%s squid", log->filename);
3171 break;
3172
3173 case CLF_COMMON:
3174 storeAppendPrintf(entry, "%s squid", log->filename);
3175 break;
3176
3177 case CLF_AUTO:
3178
3179 if (log->aclList)
3180 storeAppendPrintf(entry, "%s auto", log->filename);
3181 else
3182 storeAppendPrintf(entry, "%s", log->filename);
3183
3184 break;
3185
3186 case CLF_UNKNOWN:
3187 break;
3188 }
3189
3190 if (log->aclList)
3191 dump_acl_list(entry, log->aclList);
3192
3193 storeAppendPrintf(entry, "\n");
3194 }
3195}
3196
3197static void
3198free_logformat(logformat ** definitions)
3199{
3200 while (*definitions) {
3201 logformat *format = *definitions;
3202 *definitions = format->next;
3203 accessLogFreeLogFormat(&format->format);
3204 xfree(format);
3205 }
3206}
3207
3208static void
3209free_access_log(customlog ** definitions)
3210{
3211 while (*definitions) {
3212 customlog *log = *definitions;
3213 *definitions = log->next;
3214
3215 log->logFormat = NULL;
3216 log->type = CLF_UNKNOWN;
3217
3218 if (log->aclList)
3219 aclDestroyAclList(&log->aclList);
3220
3221 safe_free(log->filename);
3222
3223 xfree(log);
3224 }
3225}
3a69ddf3 3226
3227#if ICAP_CLIENT
3228
3229static void
3230parse_icap_service_type(ICAPConfig * cfg)
3231{
3232 cfg->parseICAPService();
3233}
3234
3235static void
3236free_icap_service_type(ICAPConfig * cfg)
3237{
3238 cfg->freeICAPService();
3239}
3240
3241static void
3242dump_icap_service_type(StoreEntry * entry, const char *name, ICAPConfig cfg)
3243{
3244 cfg.dumpICAPService(entry, name);
3245}
3246
3247static void
3248parse_icap_class_type(ICAPConfig * cfg)
3249{
3250 cfg->parseICAPClass();
3251}
3252
3253static void
3254free_icap_class_type(ICAPConfig * cfg)
3255{
3256 cfg->freeICAPClass();
3257}
3258
3259static void
3260dump_icap_class_type(StoreEntry * entry, const char *name, ICAPConfig cfg)
3261{
3262 cfg.dumpICAPClass(entry, name);
3263}
3264
3265static void
3266parse_icap_access_type(ICAPConfig * cfg)
3267{
a385afc3 3268 cfg->parseICAPAccess(LegacyParser);
3a69ddf3 3269}
3270
3271static void
3272free_icap_access_type(ICAPConfig * cfg)
3273{
3274 cfg->freeICAPAccess();
3275}
3276
3277static void
3278dump_icap_access_type(StoreEntry * entry, const char *name, ICAPConfig cfg)
3279{
3280 cfg.dumpICAPAccess(entry, name);
3281}
3282
3283#endif