]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/dnsmasq/0021-Add-ignore-address-option.patch
dnsmasq: Import more patches from upstream
[ipfire-2.x.git] / src / patches / dnsmasq / 0021-Add-ignore-address-option.patch
CommitLineData
6644c1c7
MT
1From 32fc6dbe03569d70dd394420ceb73532cf303c33 Mon Sep 17 00:00:00 2001
2From: Glen Huang <curvedmark@gmail.com>
3Date: Sat, 27 Dec 2014 15:28:12 +0000
d54a2ce4 4Subject: [PATCH 21/78] Add --ignore-address option.
6644c1c7
MT
5
6---
7 CHANGELOG | 8 ++++++++
8 man/dnsmasq.8 | 6 ++++++
9 src/dnsmasq.h | 3 ++-
10 src/forward.c | 4 ++++
11 src/option.c | 18 +++++++++++++++---
12 src/rfc1035.c | 37 +++++++++++++++++++++++++++++++++++++
13 6 files changed, 72 insertions(+), 4 deletions(-)
14
15diff --git a/CHANGELOG b/CHANGELOG
16index 956b71a151db..2b6356bcfb02 100644
17--- a/CHANGELOG
18+++ b/CHANGELOG
19@@ -22,6 +22,14 @@ version 2.73
20
21 Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids
22 for the bug report.
23+
24+ Add --ignore-address option. Ignore replies to A-record
25+ queries which include the specified address. No error is
26+ generated, dnsmasq simply continues to listen for another
27+ reply. This is useful to defeat blocking strategies which
28+ rely on quickly supplying a forged answer to a DNS
29+ request for certain domains, before the correct answer can
30+ arrive. Thanks to Glen Huang for the patch.
31
32
33 version 2.72
34diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
35index 0b8e04f0a897..4236ba307df3 100644
36--- a/man/dnsmasq.8
37+++ b/man/dnsmasq.8
38@@ -293,6 +293,12 @@ an advertising web page in response to queries for unregistered names,
39 instead of the correct NXDOMAIN response. This option tells dnsmasq to
40 fake the correct response when it sees this behaviour. As at Sept 2003
41 the IP address being returned by Verisign is 64.94.110.11
42+.TP
43+.B \-B, --ignore-address=<ipaddr>
44+Ignore replies to A-record queries which include the specified address.
45+No error is generated, dnsmasq simply continues to listen for another reply.
46+This is useful to defeat blocking strategies which rely on quickly supplying a
47+forged answer to a DNS request for certain domain, before the correct answer can arrive.
48 .TP
49 .B \-f, --filterwin2k
50 Later versions of windows make periodic DNS requests which don't get sensible answers from
51diff --git a/src/dnsmasq.h b/src/dnsmasq.h
52index 1dd61c5edba3..7bc982ddf73c 100644
53--- a/src/dnsmasq.h
54+++ b/src/dnsmasq.h
55@@ -930,7 +930,7 @@ extern struct daemon {
56 char *runfile;
57 char *lease_change_command;
58 struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
59- struct bogus_addr *bogus_addr;
60+ struct bogus_addr *bogus_addr, *ignore_addr;
61 struct server *servers;
62 struct ipsets *ipsets;
63 int log_fac; /* log facility */
64@@ -1093,6 +1093,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
65 time_t now, int *ad_reqd, int *do_bit);
66 int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
67 struct bogus_addr *addr, time_t now);
68+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
69 unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
70 size_t *len, unsigned char **p, int *is_sign);
71 int check_for_local_domain(char *name, time_t now);
72diff --git a/src/forward.c b/src/forward.c
73index 408a179a20f4..f28c7d51f708 100644
74--- a/src/forward.c
75+++ b/src/forward.c
76@@ -724,6 +724,10 @@ void reply_query(int fd, int family, time_t now)
77 if (!(forward = lookup_frec(ntohs(header->id), hash)))
78 return;
79
80+ if (daemon->ignore_addr && RCODE(header) == NOERROR &&
81+ check_for_ignored_address(header, n, daemon->ignore_addr))
82+ return;
83+
84 if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
85 !option_bool(OPT_ORDER) &&
86 forward->forwardall == 0)
87diff --git a/src/option.c b/src/option.c
88index 209fa6976609..907d0cf88de9 100644
89--- a/src/option.c
90+++ b/src/option.c
91@@ -147,6 +147,7 @@ struct myoption {
92 #define LOPT_LOCAL_SERVICE 335
93 #define LOPT_DNSSEC_TIME 336
94 #define LOPT_LOOP_DETECT 337
95+#define LOPT_IGNORE_ADDR 338
96
97 #ifdef HAVE_GETOPT_LONG
98 static const struct option opts[] =
99@@ -181,6 +182,7 @@ static const struct myoption opts[] =
100 { "local-service", 0, 0, LOPT_LOCAL_SERVICE },
101 { "bogus-priv", 0, 0, 'b' },
102 { "bogus-nxdomain", 1, 0, 'B' },
103+ { "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
104 { "selfmx", 0, 0, 'e' },
105 { "filterwin2k", 0, 0, 'f' },
106 { "pid-file", 2, 0, 'x' },
107@@ -457,6 +459,7 @@ static struct {
108 { LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
109 { LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks"), NULL },
110 { LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops"), NULL },
111+ { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL },
112 { 0, 0, NULL, NULL, NULL }
113 };
114
115@@ -2119,14 +2122,23 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
116 break;
117
118 case 'B': /* --bogus-nxdomain */
119- {
120+ case LOPT_IGNORE_ADDR: /* --ignore-address */
121+ {
122 struct in_addr addr;
123 unhide_metas(arg);
124 if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
125 {
126 struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
127- baddr->next = daemon->bogus_addr;
128- daemon->bogus_addr = baddr;
129+ if (option == 'B')
130+ {
131+ baddr->next = daemon->bogus_addr;
132+ daemon->bogus_addr = baddr;
133+ }
134+ else
135+ {
136+ baddr->next = daemon->ignore_addr;
137+ daemon->ignore_addr = baddr;
138+ }
139 baddr->addr = addr;
140 }
141 else
142diff --git a/src/rfc1035.c b/src/rfc1035.c
143index bdeb3fb10e68..75c4266b47dd 100644
144--- a/src/rfc1035.c
145+++ b/src/rfc1035.c
146@@ -1328,6 +1328,43 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
147 return 0;
148 }
149
150+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr)
151+{
152+ unsigned char *p;
153+ int i, qtype, qclass, rdlen;
154+ struct bogus_addr *baddrp;
155+
156+ /* skip over questions */
157+ if (!(p = skip_questions(header, qlen)))
158+ return 0; /* bad packet */
159+
160+ for (i = ntohs(header->ancount); i != 0; i--)
161+ {
162+ if (!(p = skip_name(p, header, qlen, 10)))
163+ return 0; /* bad packet */
164+
165+ GETSHORT(qtype, p);
166+ GETSHORT(qclass, p);
167+ p += 4; /* TTL */
168+ GETSHORT(rdlen, p);
169+
170+ if (qclass == C_IN && qtype == T_A)
171+ {
172+ if (!CHECK_LEN(header, p, qlen, INADDRSZ))
173+ return 0;
174+
175+ for (baddrp = baddr; baddrp; baddrp = baddrp->next)
176+ if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
177+ return 1;
178+ }
179+
180+ if (!ADD_RDLEN(header, p, qlen, rdlen))
181+ return 0;
182+ }
183+
184+ return 0;
185+}
186+
187 int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
188 unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
189 {
190--
1912.1.0
192