5756717340d94d2f2085b386078ab4831d5727ce
[oweals/openwrt.git] /
1 From 1f60a18ea1c64beb8b6cffa0650a2bfad95ac352 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Fri, 11 May 2018 16:44:16 +0100
4 Subject: [PATCH 07/10] Retry SERVFAIL DNSSEC queries to a different server, if
5  possible.
6
7 Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
8 ---
9  src/forward.c | 53 ++++++++++++++++++++++++++++++++++++++++++-----------
10  1 file changed, 42 insertions(+), 11 deletions(-)
11
12 --- a/src/forward.c
13 +++ b/src/forward.c
14 @@ -825,9 +825,12 @@ void reply_query(int fd, int family, tim
15        size_t plen;
16        int is_sign;
17  
18 +#ifdef HAVE_DNSSEC
19        /* For DNSSEC originated queries, just retry the query to the same server. */
20        if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
21         {
22 +         struct server *start;
23 +         
24           blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
25           plen = forward->stash_len;
26  
27 @@ -839,26 +842,54 @@ void reply_query(int fd, int family, tim
28           else
29             log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (struct all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
30  #endif
31 -  
32 -         if (forward->sentto->sfd)
33 -           fd = forward->sentto->sfd->fd;
34 +
35 +         start = forward->sentto;
36 +
37 +         /* for non-domain specific servers, see if we can find another to try. */
38 +         if ((forward->sentto->flags & SERV_TYPE) == 0)
39 +           while (1)
40 +             {
41 +               if (!(start = start->next))
42 +                 start = daemon->servers;
43 +               if (start == forward->sentto)
44 +                 break;
45 +               
46 +               if ((start->flags & SERV_TYPE) == 0 &&
47 +                   (start->flags & SERV_DO_DNSSEC))
48 +                 break;
49 +             }
50 +           
51 +         
52 +         if (start->sfd)
53 +           fd = start->sfd->fd;
54           else
55             {
56  #ifdef HAVE_IPV6
57 -             if (forward->sentto->addr.sa.sa_family == AF_INET6)
58 -               fd = forward->rfd6->fd;
59 +             if (start->addr.sa.sa_family == AF_INET6)
60 +               {
61 +                 /* may have changed family */
62 +                 if (!forward->rfd6)
63 +                   forward->rfd6 = allocate_rfd(AF_INET6);
64 +                 fd = forward->rfd6->fd;
65 +               }
66               else
67  #endif
68 -               fd = forward->rfd4->fd;
69 +               {
70 +                 /* may have changed family */
71 +                 if (!forward->rfd4)
72 +                   forward->rfd4 = allocate_rfd(AF_INET);
73 +                 fd = forward->rfd4->fd;
74 +               }
75             }
76 -         
77 +       
78           while (retry_send(sendto(fd, (char *)header, plen, 0,
79 -                                  &forward->sentto->addr.sa,
80 -                                  sa_len(&forward->sentto->addr))));
81 +                                  &start->addr.sa,
82 +                                  sa_len(&start->addr))));
83           
84           return;
85         }
86 -         
87 +#endif
88 +      
89        /* In strict order mode, there must be a server later in the chain
90          left to send to, otherwise without the forwardall mechanism,
91          code further on will cycle around the list forwever if they
92 @@ -1024,7 +1055,7 @@ void reply_query(int fd, int family, tim
93                           while (1)
94                             {
95                               if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
96 -                                 (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
97 +                                 ((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
98                                   !(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
99                                 {
100                                   new_server = start;