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