cacheResp stores the response from d in general or subnet cache. In case the cache is present in d, it's used first.
(d *DNSContext)
| 79 | // cacheResp stores the response from d in general or subnet cache. In case the |
| 80 | // cache is present in d, it's used first. |
| 81 | func (p *Proxy) cacheResp(d *DNSContext) { |
| 82 | dctxCache := p.cacheForContext(d) |
| 83 | |
| 84 | if !p.EnableEDNSClientSubnet { |
| 85 | dctxCache.set(d.Req, d.Res, d.Upstream, p.logger) |
| 86 | |
| 87 | return |
| 88 | } |
| 89 | |
| 90 | switch ecs, scope := ecsFromMsg(d.Res); { |
| 91 | case ecs != nil && d.ReqECS != nil: |
| 92 | ones, bits := ecs.Mask.Size() |
| 93 | reqOnes, _ := d.ReqECS.Mask.Size() |
| 94 | |
| 95 | // If FAMILY, SOURCE PREFIX-LENGTH, and SOURCE PREFIX-LENGTH bits of |
| 96 | // ADDRESS in the response don't match the non-zero fields in the |
| 97 | // corresponding query, the full response MUST be dropped. |
| 98 | // |
| 99 | // See RFC 7871 Section 7.3. |
| 100 | // |
| 101 | // TODO(a.meshkov): The whole response MUST be dropped if ECS in it |
| 102 | // doesn't correspond. |
| 103 | if !ecs.IP.Mask(ecs.Mask).Equal(d.ReqECS.IP.Mask(d.ReqECS.Mask)) || ones != reqOnes { |
| 104 | p.logger.Debug( |
| 105 | "not caching response; subnet mismatch", |
| 106 | "ecs", ecs, |
| 107 | "req_ecs", d.ReqECS, |
| 108 | ) |
| 109 | |
| 110 | return |
| 111 | } |
| 112 | |
| 113 | // If SCOPE PREFIX-LENGTH is not longer than SOURCE PREFIX-LENGTH, store |
| 114 | // SCOPE PREFIX-LENGTH bits of ADDRESS, and then mark the response as |
| 115 | // valid for all addresses that fall within that range. |
| 116 | // |
| 117 | // See RFC 7871 Section 7.3.1. |
| 118 | if scope < reqOnes { |
| 119 | ecs.Mask = net.CIDRMask(scope, bits) |
| 120 | ecs.IP = ecs.IP.Mask(ecs.Mask) |
| 121 | } |
| 122 | |
| 123 | p.logger.Debug("caching response", "ecs", ecs) |
| 124 | |
| 125 | dctxCache.setWithSubnet(d.Req, d.Res, d.Upstream, ecs, p.logger) |
| 126 | case d.ReqECS != nil: |
| 127 | // Cache the response for all subnets since the server doesn't support |
| 128 | // EDNS Client Subnet option. |
| 129 | dctxCache.setWithSubnet(d.Req, d.Res, d.Upstream, &net.IPNet{IP: nil, Mask: nil}, p.logger) |
| 130 | default: |
| 131 | dctxCache.set(d.Req, d.Res, d.Upstream, p.logger) |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | // ClearCache clears the DNS cache of p. |
| 136 | func (p *Proxy) ClearCache() { |