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