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