Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids
for the bug report.
+
+ Add --ignore-address option. Ignore replies to A-record
+ queries which include the specified address. No error is
+ generated, dnsmasq simply continues to listen for another
+ reply. This is useful to defeat blocking strategies which
+ rely on quickly supplying a forged answer to a DNS
+ request for certain domains, before the correct answer can
+ arrive. Thanks to Glen Huang for the patch.
version 2.72
instead of the correct NXDOMAIN response. This option tells dnsmasq to
fake the correct response when it sees this behaviour. As at Sept 2003
the IP address being returned by Verisign is 64.94.110.11
+.TP
+.B \-B, --ignore-address=<ipaddr>
+Ignore replies to A-record queries which include the specified address.
+No error is generated, dnsmasq simply continues to listen for another reply.
+This is useful to defeat blocking strategies which rely on quickly supplying a
+forged answer to a DNS request for certain domain, before the correct answer can arrive.
.TP
.B \-f, --filterwin2k
Later versions of windows make periodic DNS requests which don't get sensible answers from
char *runfile;
char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
- struct bogus_addr *bogus_addr;
+ struct bogus_addr *bogus_addr, *ignore_addr;
struct server *servers;
struct ipsets *ipsets;
int log_fac; /* log facility */
time_t now, int *ad_reqd, int *do_bit);
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *addr, time_t now);
+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign);
int check_for_local_domain(char *name, time_t now);
if (!(forward = lookup_frec(ntohs(header->id), hash)))
return;
+ if (daemon->ignore_addr && RCODE(header) == NOERROR &&
+ check_for_ignored_address(header, n, daemon->ignore_addr))
+ return;
+
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
!option_bool(OPT_ORDER) &&
forward->forwardall == 0)
#define LOPT_LOCAL_SERVICE 335
#define LOPT_DNSSEC_TIME 336
#define LOPT_LOOP_DETECT 337
+#define LOPT_IGNORE_ADDR 338
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
{ "local-service", 0, 0, LOPT_LOCAL_SERVICE },
{ "bogus-priv", 0, 0, 'b' },
{ "bogus-nxdomain", 1, 0, 'B' },
+ { "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
{ "selfmx", 0, 0, 'e' },
{ "filterwin2k", 0, 0, 'f' },
{ "pid-file", 2, 0, 'x' },
{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks"), NULL },
{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops"), NULL },
+ { LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL },
{ 0, 0, NULL, NULL, NULL }
};
break;
case 'B': /* --bogus-nxdomain */
- {
+ case LOPT_IGNORE_ADDR: /* --ignore-address */
+ {
struct in_addr addr;
unhide_metas(arg);
if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
{
struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
- baddr->next = daemon->bogus_addr;
- daemon->bogus_addr = baddr;
+ if (option == 'B')
+ {
+ baddr->next = daemon->bogus_addr;
+ daemon->bogus_addr = baddr;
+ }
+ else
+ {
+ baddr->next = daemon->ignore_addr;
+ daemon->ignore_addr = baddr;
+ }
baddr->addr = addr;
}
else
return 0;
}
+int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr)
+{
+ unsigned char *p;
+ int i, qtype, qclass, rdlen;
+ struct bogus_addr *baddrp;
+
+ /* skip over questions */
+ if (!(p = skip_questions(header, qlen)))
+ return 0; /* bad packet */
+
+ for (i = ntohs(header->ancount); i != 0; i--)
+ {
+ if (!(p = skip_name(p, header, qlen, 10)))
+ return 0; /* bad packet */
+
+ GETSHORT(qtype, p);
+ GETSHORT(qclass, p);
+ p += 4; /* TTL */
+ GETSHORT(rdlen, p);
+
+ if (qclass == C_IN && qtype == T_A)
+ {
+ if (!CHECK_LEN(header, p, qlen, INADDRSZ))
+ return 0;
+
+ for (baddrp = baddr; baddrp; baddrp = baddrp->next)
+ if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
+ return 1;
+ }
+
+ if (!ADD_RDLEN(header, p, qlen, rdlen))
+ return 0;
+ }
+
+ return 0;
+}
+
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
{