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