]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cache_cf.cc
Add 'from hostname' on X-Cache reply header line
[thirdparty/squid.git] / src / cache_cf.cc
CommitLineData
be335c22 1
30a4f2a8 2/*
16300b58 3 * $Id: cache_cf.cc,v 1.247 1998/02/06 17:50:19 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 3 Configuration File Parsing
6 * AUTHOR: Harvest Derived
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
cf5fd929 31
44a47c6e 32#include "squid.h"
1df370e3 33
34#if SQUID_SNMP
a97cfa48 35#include "snmp.h"
1df370e3 36#endif
090089c4 37
8813e606 38static const char *const T_SECOND_STR = "second";
39static const char *const T_MINUTE_STR = "minute";
40static const char *const T_HOUR_STR = "hour";
41static const char *const T_DAY_STR = "day";
42static const char *const T_WEEK_STR = "week";
43static const char *const T_FORTNIGHT_STR = "fortnight";
44static const char *const T_MONTH_STR = "month";
45static const char *const T_YEAR_STR = "year";
46static const char *const T_DECADE_STR = "decade";
aa0a0c7c 47
9906e724 48static const char *const B_BYTES_STR = "bytes";
49static const char *const B_KBYTES_STR = "KB";
50static const char *const B_MBYTES_STR = "MB";
51static const char *const B_GBYTES_STR = "GB";
52
4db43fab 53static const char *const list_sep = ", \t\n\r";
090089c4 54
24382924 55static char fatal_str[BUFSIZ];
f5b8bbc4 56static void self_destruct(void);
57static void wordlistAdd(wordlist **, const char *);
caebbe00 58
f5b8bbc4 59static void configDoConfigure(void);
1df370e3 60#if SQUID_SNMP
a97cfa48 61static void parse_snmp_conf(snmpconf **);
1df370e3 62#endif
f5b8bbc4 63static void parse_refreshpattern(refresh_t **);
64static int parseTimeUnits(const char *unit);
65static void parseTimeLine(time_t * tptr, const char *units);
66static void parse_string(char **);
67static void parse_wordlist(wordlist **);
68static void default_all(void);
69static void defaults_if_none(void);
70static int parse_line(char *);
71static void parseBytesLine(size_t * bptr, const char *units);
72static size_t parseBytesUnits(const char *unit);
f5b8bbc4 73static void free_all(void);
f0b19334 74static void requirePathnameExists(const char *name, const char *path);
270b86af 75
24382924 76static void
0673c0ba 77self_destruct(void)
090089c4 78{
56878878 79 snprintf(fatal_str, BUFSIZ, "Bungled %s line %d: %s",
b8de7ebe 80 cfg_filename, config_lineno, config_input_line);
090089c4 81 fatal(fatal_str);
82}
83
8203a132 84void
85wordlistDestroy(wordlist ** list)
0ffd22bc 86{
87 wordlist *w = NULL;
79d39a72 88 while ((w = *list) != NULL) {
b5639035 89 *list = w->next;
0ffd22bc 90 safe_free(w->key);
91 safe_free(w);
92 }
93 *list = NULL;
94}
95
24382924 96static void
fe4e214f 97wordlistAdd(wordlist ** list, const char *key)
090089c4 98{
0ffd22bc 99 wordlist *p = NULL;
100 wordlist *q = NULL;
090089c4 101
102 if (!(*list)) {
103 /* empty list */
30a4f2a8 104 *list = xcalloc(1, sizeof(wordlist));
090089c4 105 (*list)->key = xstrdup(key);
106 (*list)->next = NULL;
107 } else {
108 p = *list;
109 while (p->next)
110 p = p->next;
30a4f2a8 111 q = xcalloc(1, sizeof(wordlist));
090089c4 112 q->key = xstrdup(key);
113 q->next = NULL;
114 p->next = q;
115 }
116}
117
8203a132 118void
119intlistDestroy(intlist ** list)
92a6f4b1 120{
121 intlist *w = NULL;
122 intlist *n = NULL;
123
124 for (w = *list; w; w = n) {
125 n = w->next;
126 safe_free(w);
127 }
128 *list = NULL;
129}
130
403279e0 131
3c5557f9 132/*
133 * Use this #define in all the parse*() functions. Assumes char *token is
134 * defined
135 */
090089c4 136
137#define GetInteger(var) \
138 token = strtok(NULL, w_space); \
30a4f2a8 139 if( token == NULL) \
3003c0f3 140 self_destruct(); \
090089c4 141 if (sscanf(token, "%d", &var) != 1) \
3003c0f3 142 self_destruct();
090089c4 143
270b86af 144int
145parseConfigFile(const char *file_name)
2546fcb3 146{
270b86af 147 FILE *fp = NULL;
148 char *token = NULL;
72121e8b 149 char *tmp_line;
0153d498 150 free_all();
151 default_all();
270b86af 152 if ((fp = fopen(file_name, "r")) == NULL) {
042461c3 153 snprintf(fatal_str, BUFSIZ, "Unable to open configuration file: %s: %s",
270b86af 154 file_name, xstrerror());
155 fatal(fatal_str);
156 }
157 cfg_filename = file_name;
158 if ((token = strrchr(cfg_filename, '/')))
159 cfg_filename = token + 1;
160 memset(config_input_line, '\0', BUFSIZ);
161 config_lineno = 0;
162 while (fgets(config_input_line, BUFSIZ, fp)) {
163 config_lineno++;
164 if ((token = strchr(config_input_line, '\n')))
165 *token = '\0';
166 if (config_input_line[0] == '#')
167 continue;
168 if (config_input_line[0] == '\0')
169 continue;
170 debug(3, 5) ("Processing: '%s'\n", config_input_line);
72121e8b 171 tmp_line = xstrdup(config_input_line);
270b86af 172 if (!parse_line(tmp_line)) {
173 debug(3, 0) ("parseConfigFile: line %d unrecognized: '%s'\n",
174 config_lineno,
175 config_input_line);
176 }
72121e8b 177 safe_free(tmp_line);
270b86af 178 }
f0b19334 179 fclose(fp);
180 defaults_if_none();
181 configDoConfigure();
182 return 0;
183}
270b86af 184
f0b19334 185static void
186configDoConfigure(void)
187{
188 LOCAL_ARRAY(char, buf, BUFSIZ);
189 memset(&Config2, '\0', sizeof(SquidConfig2));
270b86af 190 /* Sanity checks */
a95856a0 191 if (Config.cacheSwap.swapDirs == NULL)
192 fatal("No cache_dir's specified in config file");
f0b19334 193 if (Config.Swap.maxSize < (Config.Mem.maxSize >> 10))
194 fatal("cache_swap is lower than cache_mem");
f1dc9b30 195 if (Config.Announce.period < 1) {
196 Config.Announce.period = 86400 * 365; /* one year */
17a0a4ee 197 Config.onoff.announce = 0;
270b86af 198 }
f0b19334 199 if (Config.dnsChildren < 1)
200 fatal("No dnsservers allocated");
201 if (Config.dnsChildren > DefaultDnsChildrenMax) {
202 debug(3, 0) ("WARNING: dns_children was set to a bad value: %d\n",
270b86af 203 Config.dnsChildren);
f0b19334 204 debug(3, 0) ("Setting it to the maximum (%d).\n",
205 DefaultDnsChildrenMax);
270b86af 206 Config.dnsChildren = DefaultDnsChildrenMax;
207 }
208 if (Config.Program.redirect) {
209 if (Config.redirectChildren < 1) {
210 Config.redirectChildren = 0;
211 safe_free(Config.Program.redirect);
212 } else if (Config.redirectChildren > DefaultRedirectChildrenMax) {
f0b19334 213 debug(3, 0) ("WARNING: redirect_children was set to a bad value: %d\n",
270b86af 214 Config.redirectChildren);
f0b19334 215 debug(3, 0) ("Setting it to the maximum (%d).\n", DefaultRedirectChildrenMax);
270b86af 216 Config.redirectChildren = DefaultRedirectChildrenMax;
217 }
fea2e6e0 218 }
f1dc9b30 219 if (Config.Accel.host) {
a47b9029 220 snprintf(buf, BUFSIZ, "http://%s:%d", Config.Accel.host, Config.Accel.port);
221 Config2.Accel.prefix = xstrdup(buf);
222 Config2.Accel.on = 1;
f1dc9b30 223 }
224 if (Config.appendDomain)
225 if (*Config.appendDomain != '.')
226 fatal("append_domain must begin with a '.'");
270b86af 227 if (Config.errHtmlText == NULL)
228 Config.errHtmlText = xstrdup(null_string);
229 storeConfigure();
f1dc9b30 230 if (Config2.Accel.on && !strcmp(Config.Accel.host, "virtual"))
270b86af 231 vhost_mode = 1;
232 if (Config.Port.http == NULL)
233 fatal("No http_port specified!");
042461c3 234 snprintf(ThisCache, SQUIDHOSTNAMELEN << 1, "%s:%d (Squid/%s)",
270b86af 235 getMyHostname(),
236 (int) Config.Port.http->i,
237 SQUID_VERSION);
238 if (!Config.udpMaxHitObjsz || Config.udpMaxHitObjsz > SQUID_UDP_SO_SNDBUF)
239 Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF;
240 if (Config.appendDomain)
241 Config.appendDomainLen = strlen(Config.appendDomain);
242 else
243 Config.appendDomainLen = 0;
f1dc9b30 244 safe_free(debug_options)
245 debug_options = xstrdup(Config.debugOptions);
22c653cd 246 if (Config.retry.timeout < 5)
247 fatal("minimum_retry_timeout must be at least 5 seconds");
248 if (Config.retry.maxtries > 10)
249 fatal("maximum_single_addr_tries cannot be larger than 10");
250 if (Config.retry.maxtries < 1) {
22c653cd 251 debug(3, 0) ("WARNING: resetting 'maximum_single_addr_tries to 1\n");
5210854d 252 Config.retry.maxtries = 1;
253 }
254 if (Config.referenceAge < 300) {
255 debug(3, 0) ("WARNING: resetting 'reference_age' to 1 week\n");
256 Config.referenceAge = 86400 * 7;
22c653cd 257 }
f0b19334 258 requirePathnameExists("MIME Config Table", Config.mimeTablePathname);
259 requirePathnameExists("cache_dns_program", Config.Program.dnsserver);
260 requirePathnameExists("unlinkd_program", Config.Program.unlinkd);
261 if (Config.Program.redirect)
262 requirePathnameExists("redirect_program", Config.Program.redirect);
263 requirePathnameExists("announce_file", Config.Announce.file);
264 requirePathnameExists("Icon Directory", Config.icons.directory);
265 requirePathnameExists("Error Directory", Config.errorDirectory);
090089c4 266}
267
270b86af 268/* Parse a time specification from the config file. Store the
f1dc9b30 269 * result in 'tptr', after converting it to 'units' */
8203a132 270static void
a47b9029 271parseTimeLine(time_t * tptr, const char *units)
090089c4 272{
273 char *token;
270b86af 274 double d;
f1dc9b30 275 time_t m;
276 time_t u;
270b86af 277 if ((u = parseTimeUnits(units)) == 0)
3003c0f3 278 self_destruct();
270b86af 279 if ((token = strtok(NULL, w_space)) == NULL)
3003c0f3 280 self_destruct();
270b86af 281 d = atof(token);
282 m = u; /* default to 'units' if none specified */
9e975e4e 283 if ((token = strtok(NULL, w_space)) == NULL)
a47b9029 284 debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n",
285 config_input_line, d, units);
9e975e4e 286 else if ((m = parseTimeUnits(token)) == 0)
a47b9029 287 self_destruct();
f1dc9b30 288 *tptr = m * d / u;
090089c4 289}
290
270b86af 291static int
292parseTimeUnits(const char *unit)
293{
294 if (!strncasecmp(unit, T_SECOND_STR, strlen(T_SECOND_STR)))
295 return 1;
296 if (!strncasecmp(unit, T_MINUTE_STR, strlen(T_MINUTE_STR)))
297 return 60;
298 if (!strncasecmp(unit, T_HOUR_STR, strlen(T_HOUR_STR)))
299 return 3600;
300 if (!strncasecmp(unit, T_DAY_STR, strlen(T_DAY_STR)))
301 return 86400;
302 if (!strncasecmp(unit, T_WEEK_STR, strlen(T_WEEK_STR)))
303 return 86400 * 7;
304 if (!strncasecmp(unit, T_FORTNIGHT_STR, strlen(T_FORTNIGHT_STR)))
305 return 86400 * 14;
306 if (!strncasecmp(unit, T_MONTH_STR, strlen(T_MONTH_STR)))
307 return 86400 * 30;
308 if (!strncasecmp(unit, T_YEAR_STR, strlen(T_YEAR_STR)))
309 return 86400 * 365.2522;
310 if (!strncasecmp(unit, T_DECADE_STR, strlen(T_DECADE_STR)))
311 return 86400 * 365.2522 * 10;
312 debug(3, 1) ("parseTimeUnits: unknown time unit '%s'\n", unit);
313 return 0;
314}
315
9906e724 316static void
9e975e4e 317parseBytesLine(size_t * bptr, const char *units)
9906e724 318{
319 char *token;
320 double d;
321 size_t m;
322 size_t u;
323 if ((u = parseBytesUnits(units)) == 0)
324 self_destruct();
325 if ((token = strtok(NULL, w_space)) == NULL)
326 self_destruct();
327 d = atof(token);
328 m = u; /* default to 'units' if none specified */
9e975e4e 329 if ((token = strtok(NULL, w_space)) == NULL)
330 debug(3, 0) ("WARNING: No units on '%s', assuming %f %s\n",
331 config_input_line, d, units);
332 else if ((m = parseBytesUnits(token)) == 0)
333 self_destruct();
9906e724 334 *bptr = m * d / u;
335}
336
337static size_t
338parseBytesUnits(const char *unit)
339{
340 if (!strncasecmp(unit, B_BYTES_STR, strlen(B_BYTES_STR)))
341 return 1;
342 if (!strncasecmp(unit, B_KBYTES_STR, strlen(B_KBYTES_STR)))
a47b9029 343 return 1 << 10;
9906e724 344 if (!strncasecmp(unit, B_MBYTES_STR, strlen(B_MBYTES_STR)))
a47b9029 345 return 1 << 20;
9906e724 346 if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR)))
a47b9029 347 return 1 << 30;
9906e724 348 debug(3, 1) ("parseBytesUnits: unknown bytes unit '%s'\n", unit);
349 return 0;
350}
351
270b86af 352/*****************************************************************************
353 * Max
354 *****************************************************************************/
355
8203a132 356static void
a7d59104 357dump_acl(StoreEntry * entry, const char *name, acl * acl)
090089c4 358{
56b63fa1 359 wordlist *w;
360 wordlist *v;
361 while (acl != NULL) {
16300b58 362 v = w = aclDumpGeneric(acl);
56b63fa1 363 while (v != NULL) {
16300b58 364 storeAppendPrintf(entry, "%s %s %s %s\n",
365 name,
366 acl->name,
367 aclTypeToStr(acl->type),
368 v->key);
56b63fa1 369 v = v->next;
370 }
371 wordlistDestroy(&w);
372 acl = acl->next;
373 }
090089c4 374}
375
1df370e3 376#if SQUID_SNMP
a97cfa48 377static void
be335c22 378parse_snmp_conf(snmpconf ** s)
a97cfa48 379{
be335c22 380 static char buff[256];
381 static char *tokens[10], *p;
382 if (Mib == NULL) {
383 if (Config.Snmp.mibPath)
384 init_mib(Config.Snmp.mibPath);
385 else
386 fatal("snmp_mib_path should be defined before any snmp_agent_conf\n");
387 }
388 p = strtok(NULL, null_string);
0e7f8c14 389 xstrncpy(buff, p, 256);
be335c22 390 tokenize(buff, tokens, 10);
be335c22 391 if (!strcmp("view", tokens[0])) {
392 if (create_view(tokens) < 0)
393 debug(49, 5) ("snmp: parse_snmpconf(): error\n");
394 } else if (!strcmp("user", tokens[0])) {
395 if (create_user(tokens) < 0)
396 debug(49, 5) ("snmp: parse_snmpconf(): error\n");
397 } else if (!strcmp("community", tokens[0])) {
398 if (create_community(tokens) < 0)
399 debug(49, 5) ("snmp: parse_snmpconf(): error\n");
400 } else
401 debug(49, 5) ("snmp: unknown directive %s\n", tokens[0]);
a97cfa48 402}
403
1df370e3 404static void
405dump_snmp_conf(StoreEntry * entry, const char *name, snmpconf * head)
406{
407 storeAppendPrintf(entry, "%s -- UNIMPLEMENTED\n", name);
408}
409
410static void
411free_snmp_conf(snmpconf ** head)
412{
413 snmpconf *t;
414 while ((t = *head) != NULL) {
415 *head = t->next;
416 safe_free(t->line);
417 safe_free(t);
418 }
419}
420#endif
421
8203a132 422static void
a47b9029 423parse_acl(acl ** acl)
090089c4 424{
f1dc9b30 425 aclParseAclLine(acl);
426}
427
428static void
a47b9029 429free_acl(acl ** acl)
f1dc9b30 430{
431 aclDestroyAcls(acl);
090089c4 432}
433
8203a132 434static void
16300b58 435dump_acl_access(StoreEntry * entry, const char *name, acl_access * head)
30a4f2a8 436{
56b63fa1 437 acl_list *l;
438 while (head != NULL) {
16300b58 439 for (l = head->acl_list; l != NULL; l = l->next) {
440 storeAppendPrintf(entry, "%s %s %s%s\n",
56b63fa1 441 name,
442 head->allow ? "Allow" : "Deny",
443 l->op ? "" : "!",
444 l->acl->name);
16300b58 445 }
56b63fa1 446 head = head->next;
447 }
30a4f2a8 448}
090089c4 449
8203a132 450static void
16300b58 451parse_acl_access(acl_access ** head)
090089c4 452{
270b86af 453 aclParseAccessLine(head);
090089c4 454}
455
0153d498 456static void
16300b58 457free_acl_access(acl_access ** head)
0153d498 458{
a47b9029 459 aclDestroyAccessList(head);
0153d498 460}
461
8203a132 462static void
a7d59104 463dump_address(StoreEntry * entry, const char *name, struct in_addr addr)
270b86af 464{
f53b06f9 465 storeAppendPrintf(entry, "%s %s\n", name, inet_ntoa(addr));
270b86af 466}
467
468static void
469parse_address(struct in_addr *addr)
090089c4 470{
0ee4272b 471 const struct hostent *hp;
270b86af 472 char *token = strtok(NULL, w_space);
473
30a4f2a8 474 if (token == NULL)
475 self_destruct();
429fdbec 476 if (safe_inet_addr(token, addr) == 1)
477 (void) 0;
ceb8994e 478 else if ((hp = gethostbyname(token))) /* dont use ipcache */
1d73e33a 479 *addr = inaddrFromHostent(hp);
30a4f2a8 480 else
3003c0f3 481 self_destruct();
090089c4 482}
483
0153d498 484static void
485free_address(struct in_addr *addr)
486{
a47b9029 487 memset(addr, '\0', sizeof(struct in_addr));
0153d498 488}
489
e90100aa 490static void
56b63fa1 491dump_cachedir(StoreEntry * entry, const char *name, cacheSwap swap)
e90100aa 492{
f53b06f9 493 SwapDir *s;
494 int i;
a7d59104 495 for (i = 0; i < swap.n_configured; i++) {
496 s = swap.swapDirs + i;
f53b06f9 497 storeAppendPrintf(entry, "%s %s %d %d %d\n",
498 name,
499 s->path,
a7d59104 500 s->max_size >> 10,
f53b06f9 501 s->l1,
502 s->l2);
503 }
504}
505
506static int
56b63fa1 507check_null_cachedir(cacheSwap swap)
f53b06f9 508{
509 return swap.swapDirs == NULL;
e90100aa 510}
511
53ad48e6 512static int
513check_null_string(char *s)
514{
515 return s == NULL;
516}
517
8203a132 518static void
16300b58 519parse_cachedir(cacheSwap * swap)
090089c4 520{
521 char *token;
7da279d6 522 char *path;
752c3b27 523 int i;
270b86af 524 int size;
525 int l1;
526 int l2;
527 int readonly = 0;
f1dc9b30 528 SwapDir *tmp = NULL;
529 if ((path = strtok(NULL, w_space)) == NULL)
752c3b27 530 self_destruct();
270b86af 531 GetInteger(i);
532 size = i << 10; /* Mbytes to kbytes */
893dbb06 533 if (size <= 0)
534 fatal("parse_cachedir: invalid size value");
270b86af 535 GetInteger(i);
536 l1 = i;
893dbb06 537 if (l1 <= 0)
538 fatal("parse_cachedir: invalid level 1 directories value");
270b86af 539 GetInteger(i);
540 l2 = i;
893dbb06 541 if (l2 <= 0)
542 fatal("parse_cachedir: invalid level 2 directories value");
270b86af 543 if ((token = strtok(NULL, w_space)))
544 if (!strcasecmp(token, "read-only"))
545 readonly = 1;
f1dc9b30 546 for (i = 0; i < swap->n_configured; i++) {
a47b9029 547 tmp = swap->swapDirs + i;
f1dc9b30 548 if (!strcmp(path, tmp->path)) {
549 /* just reconfigure it */
860ee7e3 550 if (size == tmp->max_size)
be335c22 551 debug(3, 1) ("Cache dir '%s' size remains unchanged at %d MB\n",
552 path, size);
860ee7e3 553 else
be335c22 554 debug(3, 1) ("Cache dir '%s' size changed to %d MB\n",
555 path, size);
a47b9029 556 tmp->max_size = size;
860ee7e3 557 if (tmp->read_only != readonly)
be335c22 558 debug(3, 1) ("Cache dir '%s' now %s\n",
559 readonly ? "Read-Only" : "Read-Write");
a47b9029 560 tmp->read_only = readonly;
f1dc9b30 561 return;
562 }
563 }
564 if (swap->swapDirs == NULL) {
565 swap->n_allocated = 4;
566 swap->swapDirs = xcalloc(swap->n_allocated, sizeof(SwapDir));
567 }
568 if (swap->n_allocated == swap->n_configured) {
569 swap->n_allocated <<= 1;
570 tmp = xcalloc(swap->n_allocated, sizeof(SwapDir));
571 xmemcpy(tmp, swap->swapDirs, swap->n_configured * sizeof(SwapDir));
572 xfree(swap->swapDirs);
573 swap->swapDirs = tmp;
574 }
f1dc9b30 575 tmp = swap->swapDirs + swap->n_configured;
576 tmp->path = xstrdup(path);
577 tmp->max_size = size;
578 tmp->l1 = l1;
579 tmp->l2 = l2;
580 tmp->read_only = readonly;
581 tmp->map = file_map_create(MAX_FILES_PER_DIR);
582 tmp->swaplog_fd = -1;
62607543 583 swap->n_configured++;
9906e724 584 Config.Swap.maxSize += size;
752c3b27 585}
586
8203a132 587static void
16300b58 588free_cachedir(cacheSwap * swap)
f1dc9b30 589{
a47b9029 590 SwapDir *s;
591 int i;
860ee7e3 592 /* DON'T FREE THESE FOR RECONFIGURE */
593 if (reconfigure_pending)
594 return;
a47b9029 595 for (i = 0; i < swap->n_configured; i++) {
596 s = swap->swapDirs + i;
f150dd4b 597 if (s->swaplog_fd > -1) {
598 file_close(s->swaplog_fd);
599 s->swaplog_fd = -1;
600 }
a47b9029 601 xfree(s->path);
602 filemapFreeMemory(s->map);
603 }
604 safe_free(swap->swapDirs);
605 swap->swapDirs = NULL;
606 swap->n_allocated = 0;
607 swap->n_configured = 0;
f1dc9b30 608}
609
610static void
a7d59104 611dump_peer(StoreEntry * entry, const char *name, peer * p)
98ffb7e4 612{
f53b06f9 613 storeAppendPrintf(entry, "%s -- UNIMPLEMENTED\n", name);
98ffb7e4 614}
615
8203a132 616static void
40a1495e 617parse_peer(peer ** head)
7813c6d5 618{
270b86af 619 char *token = NULL;
40a1495e 620 peer *p;
7813c6d5 621 int i;
40a1495e 622 ushortlist *u;
f9e5a344 623 const char *me = null_string; /* XXX */
40a1495e 624 p = xcalloc(1, sizeof(peer));
625 p->http_port = CACHE_HTTP_PORT;
626 p->icp_port = CACHE_ICP_PORT;
627 p->weight = 1;
dc835977 628 p->stats.logged_state = PEER_ALIVE;
e481c2dc 629 if ((token = strtok(NULL, w_space)) == NULL)
270b86af 630 self_destruct();
40a1495e 631 p->host = xstrdup(token);
e481c2dc 632 if ((token = strtok(NULL, w_space)) == NULL)
270b86af 633 self_destruct();
40a1495e 634 p->type = parseNeighborType(token);
270b86af 635 GetInteger(i);
40a1495e 636 p->http_port = (u_short) i;
7813c6d5 637 GetInteger(i);
40a1495e 638 p->icp_port = (u_short) i;
639 if (strcmp(p->host, me) == 0) {
640 for (u = Config.Port.http; u; u = u->next) {
641 if (p->http_port != u->i)
642 continue;
643 debug(15, 0) ("parse_peer: Peer looks like myself: %s %s/%d/%d\n",
644 p->type, p->host, p->http_port, p->icp_port);
645 self_destruct();
646 }
647 }
270b86af 648 while ((token = strtok(NULL, w_space))) {
649 if (!strcasecmp(token, "proxy-only")) {
40a1495e 650 p->options |= NEIGHBOR_PROXY_ONLY;
270b86af 651 } else if (!strcasecmp(token, "no-query")) {
40a1495e 652 p->options |= NEIGHBOR_NO_QUERY;
270b86af 653 } else if (!strcasecmp(token, "multicast-responder")) {
40a1495e 654 p->options |= NEIGHBOR_MCAST_RESPONDER;
270b86af 655 } else if (!strncasecmp(token, "weight=", 7)) {
40a1495e 656 p->weight = atoi(token + 7);
b3264694 657 } else if (!strncasecmp(token, "closest-only", 12)) {
658 p->options |= NEIGHBOR_CLOSEST_ONLY;
270b86af 659 } else if (!strncasecmp(token, "ttl=", 4)) {
40a1495e 660 p->mcast.ttl = atoi(token + 4);
661 if (p->mcast.ttl < 0)
662 p->mcast.ttl = 0;
663 if (p->mcast.ttl > 128)
664 p->mcast.ttl = 128;
270b86af 665 } else if (!strncasecmp(token, "default", 7)) {
40a1495e 666 p->options |= NEIGHBOR_DEFAULT_PARENT;
270b86af 667 } else if (!strncasecmp(token, "round-robin", 11)) {
40a1495e 668 p->options |= NEIGHBOR_ROUNDROBIN;
270b86af 669 } else {
40a1495e 670 debug(3, 0) ("parse_peer: token='%s'\n", token);
270b86af 671 self_destruct();
672 }
673 }
40a1495e 674 if (p->weight < 1)
675 p->weight = 1;
676 p->icp_version = ICP_VERSION_CURRENT;
677 p->tcp_up = 1;
3f6c0fb2 678 cbdataAdd(p, MEM_NONE);
0153d498 679 while (*head != NULL)
680 head = &(*head)->next;
681 *head = p;
40a1495e 682 Config.npeers++;
0153d498 683}
684
685static void
40a1495e 686free_peer(peer ** P)
0153d498 687{
40a1495e 688 peer *p;
79d39a72 689 while ((p = *P) != NULL) {
a47b9029 690 *P = p->next;
40a1495e 691 peerDestroy(p);
a47b9029 692 }
987c67d1 693 Config.npeers = 0;
270b86af 694}
695
696static void
a7d59104 697dump_cachemgrpasswd(StoreEntry * entry, const char *name, cachemgr_passwd * list)
270b86af 698{
f53b06f9 699 storeAppendPrintf(entry, "%s -- UNIMPLEMENTED\n", name);
270b86af 700}
701
702static void
a47b9029 703parse_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 704{
705 char *passwd = NULL;
706 wordlist *actions = NULL;
707 parse_string(&passwd);
708 parse_wordlist(&actions);
f1dc9b30 709 objcachePasswdAdd(head, passwd, actions);
270b86af 710 wordlistDestroy(&actions);
711}
712
713static void
a47b9029 714free_cachemgrpasswd(cachemgr_passwd ** head)
270b86af 715{
a47b9029 716 cachemgr_passwd *p;
79d39a72 717 while ((p = *head) != NULL) {
a47b9029 718 *head = p->next;
719 xfree(p->passwd);
720 xfree(p);
721 }
270b86af 722}
723
270b86af 724
8203a132 725static void
16300b58 726dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_list * var)
270b86af 727{
f53b06f9 728 storeAppendPrintf(entry, "%s -- UNIMPLEMENTED\n", name);
270b86af 729}
730
731static void
16300b58 732parse_denyinfo(acl_deny_info_list ** var)
6e40f263 733{
f1dc9b30 734 aclParseDenyInfoLine(var);
6e40f263 735}
403279e0 736
1273d501 737void
a47b9029 738free_denyinfo(acl_deny_info_list ** list)
3c5557f9 739{
56b63fa1 740 acl_deny_info_list *a = NULL;
741 acl_deny_info_list *a_next = NULL;
742 acl_name_list *l = NULL;
743 acl_name_list *l_next = NULL;
1273d501 744 for (a = *list; a; a = a_next) {
a47b9029 745 for (l = a->acl_list; l; l = l_next) {
746 l_next = l->next;
747 safe_free(l);
748 }
749 a_next = a->next;
750 safe_free(a);
1273d501 751 }
752 *list = NULL;
270b86af 753}
754
755static void
f1dc9b30 756parse_peeracl(void)
270b86af 757{
758 char *host = NULL;
759 char *aclname = NULL;
53ad48e6 760
270b86af 761 if (!(host = strtok(NULL, w_space)))
762 self_destruct();
f1dc9b30 763 while ((aclname = strtok(NULL, list_sep))) {
40a1495e 764 peer *p;
f1dc9b30 765 acl_list *L = NULL;
766 acl_list **Tail = NULL;
767 acl *a = NULL;
40a1495e 768 if ((p = peerFindByName(host)) == NULL) {
43c3424b 769 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
f1dc9b30 770 cfg_filename, config_lineno, host);
771 return;
772 }
56b63fa1 773 L = xcalloc(1, sizeof(acl_list));
f1dc9b30 774 L->op = 1;
775 if (*aclname == '!') {
776 L->op = 0;
777 aclname++;
778 }
779 debug(15, 3) ("neighborAddAcl: looking for ACL name '%s'\n", aclname);
780 a = aclFindByName(aclname);
781 if (a == NULL) {
782 debug(15, 0) ("%s line %d: %s\n",
783 cfg_filename, config_lineno, config_input_line);
784 debug(15, 0) ("neighborAddAcl: ACL name '%s' not found.\n", aclname);
785 xfree(L);
786 return;
787 }
788 L->acl = a;
789 for (Tail = &p->acls; *Tail; Tail = &(*Tail)->next);
790 *Tail = L;
791 }
270b86af 792}
793
270b86af 794static void
795parse_hostdomain(void)
796{
797 char *host = NULL;
798 char *domain = NULL;
799 if (!(host = strtok(NULL, w_space)))
800 self_destruct();
f1dc9b30 801 while ((domain = strtok(NULL, list_sep))) {
802 domain_ping *l = NULL;
803 domain_ping **L = NULL;
40a1495e 804 peer *p;
805 if ((p = peerFindByName(host)) == NULL) {
43c3424b 806 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
f1dc9b30 807 cfg_filename, config_lineno, host);
808 continue;
809 }
56b63fa1 810 l = xcalloc(1, sizeof(domain_ping));
f1dc9b30 811 l->do_ping = 1;
812 if (*domain == '!') { /* check for !.edu */
813 l->do_ping = 0;
814 domain++;
815 }
816 l->domain = xstrdup(domain);
817 for (L = &(p->pinglist); *L; L = &((*L)->next));
818 *L = l;
819 }
270b86af 820}
821
822static void
823parse_hostdomaintype(void)
824{
825 char *host = NULL;
826 char *type = NULL;
827 char *domain = NULL;
828 if (!(host = strtok(NULL, w_space)))
829 self_destruct();
830 if (!(type = strtok(NULL, w_space)))
831 self_destruct();
f1dc9b30 832 while ((domain = strtok(NULL, list_sep))) {
833 domain_type *l = NULL;
834 domain_type **L = NULL;
40a1495e 835 peer *p;
836 if ((p = peerFindByName(host)) == NULL) {
43c3424b 837 debug(15, 0) ("%s, line %d: No cache_peer '%s'\n",
f1dc9b30 838 cfg_filename, config_lineno, host);
839 return;
840 }
56b63fa1 841 l = xcalloc(1, sizeof(domain_type));
f1dc9b30 842 l->type = parseNeighborType(type);
843 l->domain = xstrdup(domain);
844 for (L = &(p->typelist); *L; L = &((*L)->next));
845 *L = l;
846 }
270b86af 847}
848
849static void
a7d59104 850dump_httpanonymizer(StoreEntry * entry, const char *name, int var)
270b86af 851{
852 switch (var) {
853 case ANONYMIZER_NONE:
f0b19334 854 storeAppendPrintf(entry, "%s off\n", name);
270b86af 855 break;
856 case ANONYMIZER_STANDARD:
f0b19334 857 storeAppendPrintf(entry, "%s paranoid\n", name);
270b86af 858 break;
859 case ANONYMIZER_PARANOID:
f0b19334 860 storeAppendPrintf(entry, "%s standard\n", name);
270b86af 861 break;
862 }
863}
864
865static void
866parse_httpanonymizer(int *var)
fa562c67 867{
868 char *token;
869 token = strtok(NULL, w_space);
870 if (token == NULL)
bba6fa8f 871 self_destruct();
fa562c67 872 if (!strcasecmp(token, "off"))
270b86af 873 *var = ANONYMIZER_NONE;
fa562c67 874 else if (!strcasecmp(token, "paranoid"))
270b86af 875 *var = ANONYMIZER_PARANOID;
fa562c67 876 else
270b86af 877 *var = ANONYMIZER_STANDARD;
878}
879
641941c0 880
270b86af 881static void
a7d59104 882dump_ushortlist(StoreEntry * entry, const char *name, ushortlist * u)
090089c4 883{
270b86af 884 while (u) {
f53b06f9 885 storeAppendPrintf(entry, "%s %d\n", name, (int) u->i);
270b86af 886 u = u->next;
887 }
888}
090089c4 889
f53b06f9 890static int
891check_null_ushortlist(ushortlist * u)
892{
893 return u == NULL;
894}
895
270b86af 896static void
897parse_ushortlist(ushortlist ** P)
898{
899 char *token;
900 int i;
901 ushortlist *u;
902 ushortlist **U;
903 while ((token = strtok(NULL, w_space))) {
904 if (sscanf(token, "%d", &i) != 1)
905 self_destruct();
906 if (i < 0)
907 i = 0;
908 u = xcalloc(1, sizeof(ushortlist));
909 u->i = (u_short) i;
910 for (U = P; *U; U = &(*U)->next);
911 *U = u;
090089c4 912 }
270b86af 913}
090089c4 914
0153d498 915static void
a47b9029 916free_ushortlist(ushortlist ** P)
0153d498 917{
a47b9029 918 ushortlist *u;
79d39a72 919 while ((u = *P) != NULL) {
a47b9029 920 *P = u->next;
921 xfree(u);
922 }
0153d498 923}
924
270b86af 925static void
a7d59104 926dump_int(StoreEntry * entry, const char *name, int var)
270b86af 927{
f53b06f9 928 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 929}
c1c29eb6 930
270b86af 931static void
932parse_int(int *var)
933{
934 char *token;
935 int i;
270b86af 936 GetInteger(i);
937 *var = i;
938}
090089c4 939
0153d498 940static void
941free_int(int *var)
942{
a47b9029 943 *var = 0;
0153d498 944}
945
270b86af 946static void
a7d59104 947dump_onoff(StoreEntry * entry, const char *name, int var)
270b86af 948{
f53b06f9 949 storeAppendPrintf(entry, "%s %s\n", name, var ? "on" : "off");
270b86af 950}
090089c4 951
270b86af 952static void
953parse_onoff(int *var)
954{
955 char *token = strtok(NULL, w_space);
090089c4 956
270b86af 957 if (token == NULL)
958 self_destruct();
959 if (!strcasecmp(token, "on") || !strcasecmp(token, "enable"))
960 *var = 1;
961 else
962 *var = 0;
963}
e90100aa 964
0153d498 965#define free_onoff free_int
f1dc9b30 966#define free_httpanonymizer free_int
f1dc9b30 967#define dump_eol dump_string
968#define free_eol free_string
30a4f2a8 969
270b86af 970static void
a7d59104 971dump_refreshpattern(StoreEntry * entry, const char *name, refresh_t * head)
270b86af 972{
f53b06f9 973 storeAppendPrintf(entry, "%s -- UNIMPLEMENTED\n", name);
270b86af 974}
090089c4 975
270b86af 976static void
f1dc9b30 977parse_refreshpattern(refresh_t ** head)
270b86af 978{
f1dc9b30 979 char *token;
980 char *pattern;
981 time_t min = 0;
982 int pct = 0;
983 time_t max = 0;
984 int i;
985 refresh_t *t;
986 regex_t comp;
987 int errcode;
988 int flags = REG_EXTENDED | REG_NOSUB;
989 if ((token = strtok(NULL, w_space)) == NULL)
990 self_destruct();
991 if (strcmp(token, "-i") == 0) {
992 flags |= REG_ICASE;
993 token = strtok(NULL, w_space);
994 } else if (strcmp(token, "+i") == 0) {
995 flags &= ~REG_ICASE;
996 token = strtok(NULL, w_space);
997 }
998 if (token == NULL)
999 self_destruct();
1000 pattern = xstrdup(token);
1001 GetInteger(i); /* token: min */
1002 min = (time_t) (i * 60); /* convert minutes to seconds */
1003 GetInteger(i); /* token: pct */
1004 pct = i;
1005 GetInteger(i); /* token: max */
1006 max = (time_t) (i * 60); /* convert minutes to seconds */
1007 if ((errcode = regcomp(&comp, pattern, flags)) != 0) {
1008 char errbuf[256];
1009 regerror(errcode, &comp, errbuf, sizeof errbuf);
1010 debug(22, 0) ("%s line %d: %s\n",
1011 cfg_filename, config_lineno, config_input_line);
1012 debug(22, 0) ("refreshAddToList: Invalid regular expression '%s': %s\n",
1013 pattern, errbuf);
1014 return;
1015 }
1016 pct = pct < 0 ? 0 : pct;
1017 max = max < 0 ? 0 : max;
1018 t = xcalloc(1, sizeof(refresh_t));
1019 t->pattern = (char *) xstrdup(pattern);
1020 t->compiled_pattern = comp;
1021 t->min = min;
1022 t->pct = pct;
1023 t->max = max;
1024 t->next = NULL;
1025 while (*head)
1026 head = &(*head)->next;
1027 *head = t;
1028 safe_free(pattern);
270b86af 1029}
090089c4 1030
270b86af 1031static void
a47b9029 1032free_refreshpattern(refresh_t ** head)
270b86af 1033{
f1dc9b30 1034 refresh_t *t;
79d39a72 1035 while ((t = *head) != NULL) {
f1dc9b30 1036 *head = t->next;
1037 safe_free(t->pattern);
1038 regfree(&t->compiled_pattern);
1039 safe_free(t);
1040 }
270b86af 1041}
12b9e9b1 1042
270b86af 1043static void
a7d59104 1044dump_regexlist(StoreEntry * entry, const char *name, relist * var)
270b86af 1045{
f53b06f9 1046 storeAppendPrintf(entry, "%s -- UNIMPLEMENTED\n", name);
270b86af 1047}
cf5fd929 1048
270b86af 1049static void
1050parse_regexlist(relist ** var)
1051{
0153d498 1052 aclParseRegexList(var);
270b86af 1053}
fb263c4c 1054
270b86af 1055static void
0153d498 1056free_regexlist(relist ** var)
270b86af 1057{
0153d498 1058 aclDestroyRegexList(*var);
1059 *var = NULL;
270b86af 1060}
7d49daab 1061
270b86af 1062static void
a7d59104 1063dump_string(StoreEntry * entry, const char *name, char *var)
270b86af 1064{
f53b06f9 1065 if (var != NULL)
a7d59104 1066 storeAppendPrintf(entry, "%s %s\n", name, var);
270b86af 1067}
98ffb7e4 1068
270b86af 1069static void
0153d498 1070parse_string(char **var)
270b86af 1071{
1072 char *token = strtok(NULL, w_space);
270b86af 1073 safe_free(*var);
1074 if (token == NULL)
1075 self_destruct();
1076 *var = xstrdup(token);
1077}
b15e6857 1078
0153d498 1079static void
1080free_string(char **var)
1081{
027acbaf 1082 safe_free(*var);
0153d498 1083}
caebbe00 1084
270b86af 1085static void
f1dc9b30 1086parse_eol(char *volatile *var)
270b86af 1087{
1088 char *token = strtok(NULL, null_string);
270b86af 1089 safe_free(*var);
f1dc9b30 1090 if (token == NULL)
1091 self_destruct();
270b86af 1092 *var = xstrdup(token);
1093}
090089c4 1094
270b86af 1095static void
a7d59104 1096dump_time_t(StoreEntry * entry, const char *name, time_t var)
090089c4 1097{
f53b06f9 1098 storeAppendPrintf(entry, "%s %d seconds\n", name, (int) var);
090089c4 1099}
1100
270b86af 1101static void
a47b9029 1102parse_time_t(time_t * var)
0ffd22bc 1103{
f1dc9b30 1104 parseTimeLine(var, T_SECOND_STR);
0ffd22bc 1105}
1106
270b86af 1107static void
a47b9029 1108free_time_t(time_t * var)
270b86af 1109{
a47b9029 1110 *var = 0;
270b86af 1111}
9906e724 1112
1113static void
a7d59104 1114dump_size_t(StoreEntry * entry, const char *name, size_t var)
1b635117 1115{
f53b06f9 1116 storeAppendPrintf(entry, "%s %d\n", name, (int) var);
1b635117 1117}
1118
1119static void
a7d59104 1120dump_b_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 1121{
f53b06f9 1122 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_BYTES_STR);
9906e724 1123}
1124
1125static void
a7d59104 1126dump_kb_size_t(StoreEntry * entry, const char *name, size_t var)
9906e724 1127{
f53b06f9 1128 storeAppendPrintf(entry, "%s %d %s\n", name, (int) var, B_KBYTES_STR);
9906e724 1129}
1130
1131static void
a47b9029 1132parse_size_t(size_t * var)
1b635117 1133{
1134 char *token;
1135 int i;
1136 GetInteger(i);
1137 *var = (size_t) i;
1138}
1139
1140static void
1141parse_b_size_t(size_t * var)
9906e724 1142{
1143 parseBytesLine(var, B_BYTES_STR);
1144}
1145
1146static void
a47b9029 1147parse_kb_size_t(size_t * var)
9906e724 1148{
1149 parseBytesLine(var, B_KBYTES_STR);
1150}
1151
1152static void
a47b9029 1153free_size_t(size_t * var)
9906e724 1154{
a47b9029 1155 *var = 0;
9906e724 1156}
1157
1b635117 1158#define free_b_size_t free_size_t
9906e724 1159#define free_kb_size_t free_size_t
1160#define free_mb_size_t free_size_t
1161#define free_gb_size_t free_size_t
090089c4 1162
8203a132 1163static void
a7d59104 1164dump_ushort(StoreEntry * entry, const char *name, u_short var)
090089c4 1165{
f53b06f9 1166 storeAppendPrintf(entry, "%s %d\n", name, var);
270b86af 1167}
090089c4 1168
0153d498 1169static void
a47b9029 1170free_ushort(u_short * u)
0153d498 1171{
1172 *u = 0;
1173}
1174
270b86af 1175static void
1176parse_ushort(u_short * var)
1177{
1178 char *token;
1179 int i;
090089c4 1180
270b86af 1181 GetInteger(i);
1182 if (i < 0)
1183 i = 0;
1184 *var = (u_short) i;
090089c4 1185}
1186
270b86af 1187static void
a7d59104 1188dump_wordlist(StoreEntry * entry, const char *name, wordlist * list)
270b86af 1189{
270b86af 1190 while (list != NULL) {
f53b06f9 1191 storeAppendPrintf(entry, "%s %s\n", name, list->key);
270b86af 1192 list = list->next;
429fdbec 1193 }
429fdbec 1194}
1195
270b86af 1196static void
1197parse_wordlist(wordlist ** list)
429fdbec 1198{
270b86af 1199 char *token;
1200
1201 while ((token = strtok(NULL, w_space)))
1202 wordlistAdd(list, token);
429fdbec 1203}
270b86af 1204
0153d498 1205#define free_wordlist wordlistDestroy
270b86af 1206
1207#include "cf_parser.c"
f1dc9b30 1208
1209peer_t
1210parseNeighborType(const char *s)
1211{
1212 if (!strcasecmp(s, "parent"))
1213 return PEER_PARENT;
1214 if (!strcasecmp(s, "neighbor"))
1215 return PEER_SIBLING;
1216 if (!strcasecmp(s, "neighbour"))
1217 return PEER_SIBLING;
1218 if (!strcasecmp(s, "sibling"))
1219 return PEER_SIBLING;
1220 if (!strcasecmp(s, "multicast"))
1221 return PEER_MULTICAST;
1222 debug(15, 0) ("WARNING: Unknown neighbor type: %s\n", s);
1223 return PEER_SIBLING;
1224}
f150dd4b 1225
1226void
1227configFreeMemory(void)
1228{
23ff6968 1229 free_all();
f150dd4b 1230}
f0b19334 1231
1232static void
1233requirePathnameExists(const char *name, const char *path)
1234{
1235 struct stat sb;
1236 char buf[MAXPATHLEN];
1237 assert(path != NULL);
1238 if (stat(path, &sb) < 0) {
1239 snprintf(buf, MAXPATHLEN, "%s: %s", path, xstrerror());
1240 fatal(buf);
1241 }
1242}