]>
Commit | Line | Data |
---|---|---|
6644c1c7 MT |
1 | From cbc652423403e3cef00e00240f6beef713142246 Mon Sep 17 00:00:00 2001 |
2 | From: Simon Kelley <simon@thekelleys.org.uk> | |
3 | Date: Sun, 21 Dec 2014 21:21:53 +0000 | |
263d0a71 | 4 | Subject: [PATCH 18/71] Make caching work for CNAMEs pointing to A/AAAA records |
6644c1c7 MT |
5 | shadowed in /etc/hosts |
6 | ||
7 | If the answer to an upstream query is a CNAME which points to an | |
8 | A/AAAA record which also exists in /etc/hosts and friends, then | |
9 | caching is suppressed, to avoid inconsistent answers. This is | |
10 | now modified to allow caching when the upstream and local A/AAAA | |
11 | records have the same value. | |
12 | --- | |
13 | src/cache.c | 34 +++++++++++++++++++++++++--------- | |
14 | 1 file changed, 25 insertions(+), 9 deletions(-) | |
15 | ||
16 | diff --git a/src/cache.c b/src/cache.c | |
17 | index f9e1d31e8c99..ff1ca6f1c352 100644 | |
18 | --- a/src/cache.c | |
19 | +++ b/src/cache.c | |
20 | @@ -322,7 +322,7 @@ static int is_expired(time_t now, struct crec *crecp) | |
21 | return 1; | |
22 | } | |
23 | ||
24 | -static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) | |
25 | +static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) | |
26 | { | |
27 | /* Scan and remove old entries. | |
28 | If (flags & F_FORWARD) then remove any forward entries for name and any expired | |
29 | @@ -331,8 +331,8 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign | |
30 | entries in the whole cache. | |
31 | If (flags == 0) remove any expired entries in the whole cache. | |
32 | ||
33 | - In the flags & F_FORWARD case, the return code is valid, and returns zero if the | |
34 | - name exists in the cache as a HOSTS or DHCP entry (these are never deleted) | |
35 | + In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer | |
36 | + to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted) | |
37 | ||
38 | We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal> | |
39 | so that when we hit an entry which isn't reverse and is immortal, we're done. */ | |
40 | @@ -361,7 +361,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign | |
41 | (((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS)))) | |
42 | { | |
43 | if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) | |
44 | - return 0; | |
45 | + return crecp; | |
46 | *up = crecp->hash_next; | |
47 | cache_unlink(crecp); | |
48 | cache_free(crecp); | |
49 | @@ -378,7 +378,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign | |
50 | crecp->addr.sig.type_covered == addr->addr.dnssec.type)) | |
51 | { | |
52 | if (crecp->flags & F_CONFIG) | |
53 | - return 0; | |
54 | + return crecp; | |
55 | *up = crecp->hash_next; | |
56 | cache_unlink(crecp); | |
57 | cache_free(crecp); | |
58 | @@ -423,7 +423,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign | |
59 | up = &crecp->hash_next; | |
60 | } | |
61 | ||
62 | - return 1; | |
63 | + return NULL; | |
64 | } | |
65 | ||
66 | /* Note: The normal calling sequence is | |
67 | @@ -471,10 +471,26 @@ struct crec *cache_insert(char *name, struct all_addr *addr, | |
68 | return NULL; | |
69 | ||
70 | /* First remove any expired entries and entries for the name/address we | |
71 | - are currently inserting. Fail if we attempt to delete a name from | |
72 | - /etc/hosts or DHCP. */ | |
73 | - if (!cache_scan_free(name, addr, now, flags)) | |
74 | + are currently inserting. */ | |
75 | + if ((new = cache_scan_free(name, addr, now, flags))) | |
76 | { | |
77 | + /* We're trying to insert a record over one from | |
78 | + /etc/hosts or DHCP, or other config. If the | |
79 | + existing record is for an A or AAAA and | |
80 | + the record we're trying to insert is the same, | |
81 | + just drop the insert, but don't error the whole process. */ | |
82 | + if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD)) | |
83 | + { | |
84 | + if ((flags & F_IPV4) && (new->flags & F_IPV4) && | |
85 | + new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr) | |
86 | + return new; | |
87 | +#ifdef HAVE_IPV6 | |
88 | + else if ((flags & F_IPV6) && (new->flags & F_IPV6) && | |
89 | + IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6)) | |
90 | + return new; | |
91 | +#endif | |
92 | + } | |
93 | + | |
94 | insert_error = 1; | |
95 | return NULL; | |
96 | } | |
97 | -- | |
98 | 2.1.0 | |
99 |