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