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