mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0ce3c12f2 | ||
|
|
93cf516bf1 | ||
|
|
6f4de018af | ||
|
|
6e91cf3172 | ||
|
|
9cb7f8a655 | ||
|
|
5d8d1ad14b | ||
|
|
cac9ca38f6 | ||
|
|
c4523639d5 | ||
|
|
1ce1c6beae | ||
|
|
51d56df7a3 | ||
|
|
860a9a57d6 | ||
|
|
c83e33d608 | ||
|
|
7b80c75d9d | ||
|
|
79337f99ae | ||
|
|
a42ee397f3 | ||
|
|
e58f8bb8c1 | ||
|
|
58cf958e41 | ||
|
|
06d01f7ae4 | ||
|
|
1a33eec0ba | ||
|
|
82de7a1e96 | ||
|
|
8e9bde57c5 | ||
|
|
1bb70e08be | ||
|
|
9afcb7ae61 | ||
|
|
545c4955e6 | ||
|
|
2f2d59b35c |
No files matched your search
@@ -86,6 +86,12 @@ version 2.86
|
|||||||
conntrack is configured. Thanks to Yick Xie for spotting
|
conntrack is configured. Thanks to Yick Xie for spotting
|
||||||
the lack of this.
|
the lack of this.
|
||||||
|
|
||||||
|
When --dhcp-hostsfile --dhcp-optsfile and --addn-hosts are
|
||||||
|
given a directory as argument, define the order in which
|
||||||
|
files within that directory are read (alphabetical order
|
||||||
|
of filename). Thanks to Ed Wildgoose for the initial patch
|
||||||
|
and motivation for this.
|
||||||
|
|
||||||
|
|
||||||
version 2.85
|
version 2.85
|
||||||
Fix problem with DNS retries in 2.83/2.84.
|
Fix problem with DNS retries in 2.83/2.84.
|
||||||
@@ -157,6 +163,9 @@ version 2.85
|
|||||||
Tweak TFTP code to check sender of all received packets, as
|
Tweak TFTP code to check sender of all received packets, as
|
||||||
specified in RFC 1350 para 4.
|
specified in RFC 1350 para 4.
|
||||||
|
|
||||||
|
Support some wildcard matching of input tags to --tag-if.
|
||||||
|
Thanks to Geoff Back for the idea and the patch.
|
||||||
|
|
||||||
|
|
||||||
version 2.84
|
version 2.84
|
||||||
Fix a problem, introduced in 2.83, which could see DNS replies
|
Fix a problem, introduced in 2.83, which could see DNS replies
|
||||||
|
|||||||
Vendored
+6
@@ -1,3 +1,9 @@
|
|||||||
|
dnsmasq (2.87-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 08 Sep 2021 23:11:25 +0000
|
||||||
|
|
||||||
dnsmasq (2.86-1) unstable; urgency=low
|
dnsmasq (2.86-1) unstable; urgency=low
|
||||||
|
|
||||||
* Fix debian/changelog format error. (closes: #986626)
|
* Fix debian/changelog format error. (closes: #986626)
|
||||||
|
|||||||
+14
-6
@@ -1,4 +1,4 @@
|
|||||||
.TH DNSMASQ 8 2020-04-05
|
.TH DNSMASQ 8 2021-08-16
|
||||||
.SH NAME
|
.SH NAME
|
||||||
dnsmasq \- A lightweight DHCP and caching DNS server.
|
dnsmasq \- A lightweight DHCP and caching DNS server.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -55,7 +55,8 @@ Don't read the hostnames in /etc/hosts.
|
|||||||
.B \-H, --addn-hosts=<file>
|
.B \-H, --addn-hosts=<file>
|
||||||
Additional hosts file. Read the specified file as well as /etc/hosts. If \fB--no-hosts\fP is given, read
|
Additional hosts file. Read the specified file as well as /etc/hosts. If \fB--no-hosts\fP is given, read
|
||||||
only the specified file. This option may be repeated for more than one
|
only the specified file. This option may be repeated for more than one
|
||||||
additional hosts file. If a directory is given, then read all the files contained in that directory.
|
additional hosts file. If a directory is given, then read all the files contained in that directory
|
||||||
|
in alphabetical order.
|
||||||
.TP
|
.TP
|
||||||
.B --hostsdir=<path>
|
.B --hostsdir=<path>
|
||||||
Read all the hosts files contained in the directory. New or changed files
|
Read all the hosts files contained in the directory. New or changed files
|
||||||
@@ -905,7 +906,7 @@ compiled in and the kernel must have conntrack support
|
|||||||
included and configured. This option cannot be combined with
|
included and configured. This option cannot be combined with
|
||||||
.B --query-port.
|
.B --query-port.
|
||||||
.TP
|
.TP
|
||||||
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>][,<netmask>[,<broadcast>]][,<lease time>]
|
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>[,<netmask>[,<broadcast>]]][,<lease time>]
|
||||||
.TP
|
.TP
|
||||||
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
|
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
|
||||||
|
|
||||||
@@ -1165,7 +1166,7 @@ has both wired and wireless interfaces.
|
|||||||
.TP
|
.TP
|
||||||
.B --dhcp-hostsfile=<path>
|
.B --dhcp-hostsfile=<path>
|
||||||
Read DHCP host information from the specified file. If a directory
|
Read DHCP host information from the specified file. If a directory
|
||||||
is given, then read all the files contained in that directory. The file contains
|
is given, then read all the files contained in that directory in alphabetical order. The file contains
|
||||||
information about one host per line. The format of a line is the same
|
information about one host per line. The format of a line is the same
|
||||||
as text to the right of '=' in \fB--dhcp-host\fP. The advantage of storing DHCP host information
|
as text to the right of '=' in \fB--dhcp-host\fP. The advantage of storing DHCP host information
|
||||||
in this file is that it can be changed without re-starting dnsmasq:
|
in this file is that it can be changed without re-starting dnsmasq:
|
||||||
@@ -1173,7 +1174,7 @@ the file will be re-read when dnsmasq receives SIGHUP.
|
|||||||
.TP
|
.TP
|
||||||
.B --dhcp-optsfile=<path>
|
.B --dhcp-optsfile=<path>
|
||||||
Read DHCP option information from the specified file. If a directory
|
Read DHCP option information from the specified file. If a directory
|
||||||
is given, then read all the files contained in that directory. The advantage of
|
is given, then read all the files contained in that directory in alphabetical order. The advantage of
|
||||||
using this option is the same as for \fB--dhcp-hostsfile\fP: the
|
using this option is the same as for \fB--dhcp-hostsfile\fP: the
|
||||||
\fB--dhcp-optsfile\fP will be re-read when dnsmasq receives SIGHUP. Note that
|
\fB--dhcp-optsfile\fP will be re-read when dnsmasq receives SIGHUP. Note that
|
||||||
it is possible to encode the information in a
|
it is possible to encode the information in a
|
||||||
@@ -1188,7 +1189,8 @@ directory, and not an individual file. Changed or new files within
|
|||||||
the directory are read automatically, without the need to send SIGHUP.
|
the directory are read automatically, without the need to send SIGHUP.
|
||||||
If a file is deleted or changed after it has been read by dnsmasq, then the
|
If a file is deleted or changed after it has been read by dnsmasq, then the
|
||||||
host record it contained will remain until dnsmasq receives a SIGHUP, or
|
host record it contained will remain until dnsmasq receives a SIGHUP, or
|
||||||
is restarted; ie host records are only added dynamically.
|
is restarted; ie host records are only added dynamically. The order in which the
|
||||||
|
files in a directory are read is not defined.
|
||||||
.TP
|
.TP
|
||||||
.B --dhcp-optsdir=<path>
|
.B --dhcp-optsdir=<path>
|
||||||
This is equivalent to \fB--dhcp-optsfile\fP, with the differences noted for \fB--dhcp-hostsdir\fP.
|
This is equivalent to \fB--dhcp-optsfile\fP, with the differences noted for \fB--dhcp-hostsdir\fP.
|
||||||
@@ -1433,6 +1435,12 @@ Any number of set: and tag: forms may appear, in any order.
|
|||||||
tag set by another
|
tag set by another
|
||||||
.B --tag-if,
|
.B --tag-if,
|
||||||
the line which sets the tag must precede the one which tests it.
|
the line which sets the tag must precede the one which tests it.
|
||||||
|
|
||||||
|
As an extension, the tag:<tag> clauses support limited wildcard matching,
|
||||||
|
similar to the matching in the \fB--interface\fP directive. This allows, for
|
||||||
|
example, using \fB--tag-if=set:ppp,tag:ppp*\fP to set the tag 'ppp' for all requests
|
||||||
|
received on any matching interface (ppp0, ppp1, etc). This can be used in conjunction
|
||||||
|
with the tag:!<tag> format meaning that no tag matching the wildcard may be set.
|
||||||
.TP
|
.TP
|
||||||
.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
|
.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
|
||||||
When all the given tags appear in the tag set ignore the host and do
|
When all the given tags appear in the tag set ignore the host and do
|
||||||
|
|||||||
+729
-577
File diff suppressed because it is too large.
Load diff
+20
-20
@@ -210,7 +210,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (local_query || in_zone(zone, intr->name, NULL))
|
if (local_query || in_zone(zone, intr->name, NULL))
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL, 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL,
|
daemon->auth_ttl, NULL,
|
||||||
T_PTR, C_IN, "d", intr->name))
|
T_PTR, C_IN, "d", intr->name))
|
||||||
@@ -234,7 +234,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
strcat(name, ".");
|
strcat(name, ".");
|
||||||
strcat(name, zone->domain);
|
strcat(name, zone->domain);
|
||||||
}
|
}
|
||||||
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
|
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid), 0);
|
||||||
found = 1;
|
found = 1;
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL,
|
daemon->auth_ttl, NULL,
|
||||||
@@ -243,7 +243,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
|
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
|
||||||
{
|
{
|
||||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid), 0);
|
||||||
found = 1;
|
found = 1;
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL,
|
daemon->auth_ttl, NULL,
|
||||||
@@ -257,7 +257,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (!found && is_rev_synth(flag, &addr, name) && (local_query || in_zone(zone, name, NULL)))
|
if (!found && is_rev_synth(flag, &addr, name) && (local_query || in_zone(zone, name, NULL)))
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL);
|
log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL, 0);
|
||||||
found = 1;
|
found = 1;
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
@@ -269,7 +269,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (found)
|
if (found)
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
else
|
else
|
||||||
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
|
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL, 0);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -300,7 +300,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (rc == 2 && qtype == T_MX)
|
if (rc == 2 && qtype == T_MX)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
|
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||||
anscount++;
|
anscount++;
|
||||||
@@ -315,7 +315,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (rc == 2 && qtype == T_SRV)
|
if (rc == 2 && qtype == T_SRV)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
NULL, T_SRV, C_IN, "sssd",
|
NULL, T_SRV, C_IN, "sssd",
|
||||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||||
@@ -349,7 +349,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (rc == 2 && txt->class == qtype)
|
if (rc == 2 && txt->class == qtype)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, txt->class));
|
log_query(F_CONFIG | F_RRNAME, name, NULL, NULL, txt->class);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
||||||
anscount++;
|
anscount++;
|
||||||
@@ -363,7 +363,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (rc == 2 && qtype == T_TXT)
|
if (rc == 2 && qtype == T_TXT)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
|
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
|
||||||
anscount++;
|
anscount++;
|
||||||
@@ -377,7 +377,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (rc == 2 && qtype == T_NAPTR)
|
if (rc == 2 && qtype == T_NAPTR)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
NULL, T_NAPTR, C_IN, "sszzzd",
|
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||||
@@ -407,7 +407,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL, 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
qtype == T_A ? "4" : "6", &addrlist->addr))
|
qtype == T_A ? "4" : "6", &addrlist->addr))
|
||||||
@@ -420,7 +420,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
found = 1;
|
found = 1;
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
|
|
||||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
|
daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
|
||||||
anscount++;
|
anscount++;
|
||||||
@@ -434,7 +434,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
{
|
{
|
||||||
auth = soa = 1; /* inhibits auth section */
|
auth = soa = 1; /* inhibits auth section */
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>", 0);
|
||||||
}
|
}
|
||||||
else if (qtype == T_AXFR)
|
else if (qtype == T_AXFR)
|
||||||
{
|
{
|
||||||
@@ -471,14 +471,14 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
axfr = 1;
|
axfr = 1;
|
||||||
found = 1;
|
found = 1;
|
||||||
axfroffset = nameoffset;
|
axfroffset = nameoffset;
|
||||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>", 0);
|
||||||
}
|
}
|
||||||
else if (qtype == T_NS)
|
else if (qtype == T_NS)
|
||||||
{
|
{
|
||||||
auth = 1;
|
auth = 1;
|
||||||
ns = 1; /* inhibits auth section */
|
ns = 1; /* inhibits auth section */
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,7 +496,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
(local_query || filter_zone(zone, flag, &(crecp->addr))))
|
(local_query || filter_zone(zone, flag, &(crecp->addr))))
|
||||||
{
|
{
|
||||||
*cut = '.'; /* restore domain part */
|
*cut = '.'; /* restore domain part */
|
||||||
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid));
|
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
|
||||||
*cut = 0; /* remove domain part */
|
*cut = 0; /* remove domain part */
|
||||||
found = 1;
|
found = 1;
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
@@ -518,7 +518,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr))))
|
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr))))
|
||||||
{
|
{
|
||||||
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid));
|
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
|
||||||
found = 1;
|
found = 1;
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
@@ -566,7 +566,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (candidate)
|
if (candidate)
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
log_query(F_CONFIG | F_CNAME, name, NULL, NULL, 0);
|
||||||
strcpy(name, candidate->target);
|
strcpy(name, candidate->target);
|
||||||
if (!strchr(name, '.'))
|
if (!strchr(name, '.'))
|
||||||
{
|
{
|
||||||
@@ -584,7 +584,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
else if (cache_find_non_terminal(name, now))
|
else if (cache_find_non_terminal(name, now))
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
|
|
||||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -892,7 +892,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
header->nscount = htons(0);
|
header->nscount = htons(0);
|
||||||
addr.log.rcode = REFUSED;
|
addr.log.rcode = REFUSED;
|
||||||
addr.log.ede = EDE_NOT_AUTH;
|
addr.log.ede = EDE_NOT_AUTH;
|
||||||
log_query(F_UPSTREAM | F_RCODE, "error", &addr, NULL);
|
log_query(F_UPSTREAM | F_RCODE, "error", &addr, NULL, 0);
|
||||||
return resize_packet(header, ansp - (unsigned char *)header, NULL, 0);
|
return resize_packet(header, ansp - (unsigned char *)header, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+107
-49
@@ -30,50 +30,100 @@ static struct crec *really_insert(char *name, union all_addr *addr, unsigned sho
|
|||||||
time_t now, unsigned long ttl, unsigned int flags);
|
time_t now, unsigned long ttl, unsigned int flags);
|
||||||
|
|
||||||
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
||||||
|
/* taken from https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml */
|
||||||
static const struct {
|
static const struct {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
const char * const name;
|
const char * const name;
|
||||||
} typestr[] = {
|
} typestr[] = {
|
||||||
{ 1, "A" },
|
{ 1, "A" }, /* a host address [RFC1035] */
|
||||||
{ 2, "NS" },
|
{ 2, "NS" }, /* an authoritative name server [RFC1035] */
|
||||||
{ 5, "CNAME" },
|
{ 3, "MD" }, /* a mail destination (OBSOLETE - use MX) [RFC1035] */
|
||||||
{ 6, "SOA" },
|
{ 4, "MF" }, /* a mail forwarder (OBSOLETE - use MX) [RFC1035] */
|
||||||
{ 10, "NULL" },
|
{ 5, "CNAME" }, /* the canonical name for an alias [RFC1035] */
|
||||||
{ 11, "WKS" },
|
{ 6, "SOA" }, /* marks the start of a zone of authority [RFC1035] */
|
||||||
{ 12, "PTR" },
|
{ 7, "MB" }, /* a mailbox domain name (EXPERIMENTAL) [RFC1035] */
|
||||||
{ 13, "HINFO" },
|
{ 8, "MG" }, /* a mail group member (EXPERIMENTAL) [RFC1035] */
|
||||||
{ 15, "MX" },
|
{ 9, "MR" }, /* a mail rename domain name (EXPERIMENTAL) [RFC1035] */
|
||||||
{ 16, "TXT" },
|
{ 10, "NULL" }, /* a null RR (EXPERIMENTAL) [RFC1035] */
|
||||||
{ 22, "NSAP" },
|
{ 11, "WKS" }, /* a well known service description [RFC1035] */
|
||||||
{ 23, "NSAP_PTR" },
|
{ 12, "PTR" }, /* a domain name pointer [RFC1035] */
|
||||||
{ 24, "SIG" },
|
{ 13, "HINFO" }, /* host information [RFC1035] */
|
||||||
{ 25, "KEY" },
|
{ 14, "MINFO" }, /* mailbox or mail list information [RFC1035] */
|
||||||
{ 28, "AAAA" },
|
{ 15, "MX" }, /* mail exchange [RFC1035] */
|
||||||
{ 29, "LOC" },
|
{ 16, "TXT" }, /* text strings [RFC1035] */
|
||||||
{ 33, "SRV" },
|
{ 17, "RP" }, /* for Responsible Person [RFC1183] */
|
||||||
{ 35, "NAPTR" },
|
{ 18, "AFSDB" }, /* for AFS Data Base location [RFC1183][RFC5864] */
|
||||||
{ 36, "KX" },
|
{ 19, "X25" }, /* for X.25 PSDN address [RFC1183] */
|
||||||
{ 37, "CERT" },
|
{ 20, "ISDN" }, /* for ISDN address [RFC1183] */
|
||||||
{ 38, "A6" },
|
{ 21, "RT" }, /* for Route Through [RFC1183] */
|
||||||
{ 39, "DNAME" },
|
{ 22, "NSAP" }, /* for NSAP address, NSAP style A record [RFC1706] */
|
||||||
{ 41, "OPT" },
|
{ 23, "NSAP_PTR" }, /* for domain name pointer, NSAP style [RFC1348][RFC1637][RFC1706] */
|
||||||
{ 43, "DS" },
|
{ 24, "SIG" }, /* for security signature [RFC2535][RFC2536][RFC2537][RFC2931][RFC3008][RFC3110][RFC3755][RFC4034] */
|
||||||
{ 46, "RRSIG" },
|
{ 25, "KEY" }, /* for security key [RFC2535][RFC2536][RFC2537][RFC2539][RFC3008][RFC3110][RFC3755][RFC4034] */
|
||||||
{ 47, "NSEC" },
|
{ 26, "PX" }, /* X.400 mail mapping information [RFC2163] */
|
||||||
{ 48, "DNSKEY" },
|
{ 27, "GPOS" }, /* Geographical Position [RFC1712] */
|
||||||
{ 50, "NSEC3" },
|
{ 28, "AAAA" }, /* IP6 Address [RFC3596] */
|
||||||
{ 51, "NSEC3PARAM" },
|
{ 29, "LOC" }, /* Location Information [RFC1876] */
|
||||||
{ 52, "TLSA" },
|
{ 30, "NXT" }, /* Next Domain (OBSOLETE) [RFC2535][RFC3755] */
|
||||||
{ 53, "SMIMEA" },
|
{ 31, "EID" }, /* Endpoint Identifier [Michael_Patton][http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt] 1995-06*/
|
||||||
{ 55, "HIP" },
|
{ 32, "NIMLOC" }, /* Nimrod Locator [1][Michael_Patton][http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt] 1995-06*/
|
||||||
{ 249, "TKEY" },
|
{ 33, "SRV" }, /* Server Selection [1][RFC2782] */
|
||||||
{ 250, "TSIG" },
|
{ 34, "ATMA" }, /* ATM Address [ ATM Forum Technical Committee, "ATM Name System, V2.0", Doc ID: AF-DANS-0152.000, July 2000. Available from and held in escrow by IANA.] */
|
||||||
{ 251, "IXFR" },
|
{ 35, "NAPTR" }, /* Naming Authority Pointer [RFC2168][RFC2915][RFC3403] */
|
||||||
{ 252, "AXFR" },
|
{ 36, "KX" }, /* Key Exchanger [RFC2230] */
|
||||||
{ 253, "MAILB" },
|
{ 37, "CERT" }, /* CERT [RFC4398] */
|
||||||
{ 254, "MAILA" },
|
{ 38, "A6" }, /* A6 (OBSOLETE - use AAAA) [RFC2874][RFC3226][RFC6563] */
|
||||||
{ 255, "ANY" },
|
{ 39, "DNAME" }, /* DNAME [RFC6672] */
|
||||||
{ 257, "CAA" }
|
{ 40, "SINK" }, /* SINK [Donald_E_Eastlake][http://tools.ietf.org/html/draft-eastlake-kitchen-sink] 1997-11*/
|
||||||
|
{ 41, "OPT" }, /* OPT [RFC3225][RFC6891] */
|
||||||
|
{ 42, "APL" }, /* APL [RFC3123] */
|
||||||
|
{ 43, "DS" }, /* Delegation Signer [RFC3658][RFC4034] */
|
||||||
|
{ 44, "SSHFP" }, /* SSH Key Fingerprint [RFC4255] */
|
||||||
|
{ 45, "IPSECKEY" }, /* IPSECKEY [RFC4025] */
|
||||||
|
{ 46, "RRSIG" }, /* RRSIG [RFC3755][RFC4034] */
|
||||||
|
{ 47, "NSEC" }, /* NSEC [RFC3755][RFC4034][RFC9077] */
|
||||||
|
{ 48, "DNSKEY" }, /* DNSKEY [RFC3755][RFC4034] */
|
||||||
|
{ 49, "DHCID" }, /* DHCID [RFC4701] */
|
||||||
|
{ 50, "NSEC3" }, /* NSEC3 [RFC5155][RFC9077] */
|
||||||
|
{ 51, "NSEC3PARAM" }, /* NSEC3PARAM [RFC5155] */
|
||||||
|
{ 52, "TLSA" }, /* TLSA [RFC6698] */
|
||||||
|
{ 53, "SMIMEA" }, /* S/MIME cert association [RFC8162] SMIMEA/smimea-completed-template 2015-12-01*/
|
||||||
|
{ 55, "HIP" }, /* Host Identity Protocol [RFC8005] */
|
||||||
|
{ 56, "NINFO" }, /* NINFO [Jim_Reid] NINFO/ninfo-completed-template 2008-01-21*/
|
||||||
|
{ 57, "RKEY" }, /* RKEY [Jim_Reid] RKEY/rkey-completed-template 2008-01-21*/
|
||||||
|
{ 58, "TALINK" }, /* Trust Anchor LINK [Wouter_Wijngaards] TALINK/talink-completed-template 2010-02-17*/
|
||||||
|
{ 59, "CDS" }, /* Child DS [RFC7344] CDS/cds-completed-template 2011-06-06*/
|
||||||
|
{ 60, "CDNSKEY" }, /* DNSKEY(s) the Child wants reflected in DS [RFC7344] 2014-06-16*/
|
||||||
|
{ 61, "OPENPGPKEY" }, /* OpenPGP Key [RFC7929] OPENPGPKEY/openpgpkey-completed-template 2014-08-12*/
|
||||||
|
{ 62, "CSYNC" }, /* Child-To-Parent Synchronization [RFC7477] 2015-01-27*/
|
||||||
|
{ 63, "ZONEMD" }, /* Message Digest Over Zone Data [RFC8976] ZONEMD/zonemd-completed-template 2018-12-12*/
|
||||||
|
{ 64, "SVCB" }, /* Service Binding [draft-ietf-dnsop-svcb-https-00] SVCB/svcb-completed-template 2020-06-30*/
|
||||||
|
{ 65, "HTTPS" }, /* HTTPS Binding [draft-ietf-dnsop-svcb-https-00] HTTPS/https-completed-template 2020-06-30*/
|
||||||
|
{ 99, "SPF" }, /* [RFC7208] */
|
||||||
|
{ 100, "UINFO" }, /* [IANA-Reserved] */
|
||||||
|
{ 101, "UID" }, /* [IANA-Reserved] */
|
||||||
|
{ 102, "GID" }, /* [IANA-Reserved] */
|
||||||
|
{ 103, "UNSPEC" }, /* [IANA-Reserved] */
|
||||||
|
{ 104, "NID" }, /* [RFC6742] ILNP/nid-completed-template */
|
||||||
|
{ 105, "L32" }, /* [RFC6742] ILNP/l32-completed-template */
|
||||||
|
{ 106, "L64" }, /* [RFC6742] ILNP/l64-completed-template */
|
||||||
|
{ 107, "LP" }, /* [RFC6742] ILNP/lp-completed-template */
|
||||||
|
{ 108, "EUI48" }, /* an EUI-48 address [RFC7043] EUI48/eui48-completed-template 2013-03-27*/
|
||||||
|
{ 109, "EUI64" }, /* an EUI-64 address [RFC7043] EUI64/eui64-completed-template 2013-03-27*/
|
||||||
|
{ 249, "TKEY" }, /* Transaction Key [RFC2930] */
|
||||||
|
{ 250, "TSIG" }, /* Transaction Signature [RFC8945] */
|
||||||
|
{ 251, "IXFR" }, /* incremental transfer [RFC1995] */
|
||||||
|
{ 252, "AXFR" }, /* transfer of an entire zone [RFC1035][RFC5936] */
|
||||||
|
{ 253, "MAILB" }, /* mailbox-related RRs (MB, MG or MR) [RFC1035] */
|
||||||
|
{ 254, "MAILA" }, /* mail agent RRs (OBSOLETE - see MX) [RFC1035] */
|
||||||
|
{ 255, "ANY" }, /* A request for some or all records the server has available [RFC1035][RFC6895][RFC8482] */
|
||||||
|
{ 256, "URI" }, /* URI [RFC7553] URI/uri-completed-template 2011-02-22*/
|
||||||
|
{ 257, "CAA" }, /* Certification Authority Restriction [RFC8659] CAA/caa-completed-template 2011-04-07*/
|
||||||
|
{ 258, "AVC" }, /* Application Visibility and Control [Wolfgang_Riedel] AVC/avc-completed-template 2016-02-26*/
|
||||||
|
{ 259, "DOA" }, /* Digital Object Architecture [draft-durand-doa-over-dns] DOA/doa-completed-template 2017-08-30*/
|
||||||
|
{ 260, "AMTRELAY" }, /* Automatic Multicast Tunneling Relay [RFC8777] AMTRELAY/amtrelay-completed-template 2019-02-06*/
|
||||||
|
{ 32768, "TA" }, /* DNSSEC Trust Authorities [Sam_Weiler][http://cameo.library.cmu.edu/][ Deploying DNSSEC Without a Signed Root. Technical Report 1999-19, Information Networking Institute, Carnegie Mellon University, April 2004.] 2005-12-13*/
|
||||||
|
{ 32769, "DLV" }, /* DNSSEC Lookaside Validation (OBSOLETE) [RFC8749][RFC4431] */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cache_free(struct crec *crecp);
|
static void cache_free(struct crec *crecp);
|
||||||
@@ -488,8 +538,6 @@ struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* Don't log DNSSEC records here, done elsewhere */
|
|
||||||
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
|
||||||
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
|
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
|
||||||
ttl = daemon->max_cache_ttl;
|
ttl = daemon->max_cache_ttl;
|
||||||
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
|
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
|
||||||
@@ -1807,7 +1855,7 @@ char *record_source(unsigned int index)
|
|||||||
return "<unknown>";
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
char *querystr(char *desc, unsigned short type)
|
static char *querystr(char *desc, unsigned short type)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int len = 10; /* strlen("type=xxxxx") */
|
int len = 10; /* strlen("type=xxxxx") */
|
||||||
@@ -1855,7 +1903,7 @@ char *querystr(char *desc, unsigned short type)
|
|||||||
if (types)
|
if (types)
|
||||||
sprintf(buff, "<%s>", types);
|
sprintf(buff, "<%s>", types);
|
||||||
else
|
else
|
||||||
sprintf(buff, "type=%d", type);
|
sprintf(buff, "<type=%d>", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1895,19 +1943,30 @@ static char *edestr(int ede)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
|
void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, unsigned short type)
|
||||||
{
|
{
|
||||||
char *source, *dest = daemon->addrbuff;
|
char *source, *dest = arg;
|
||||||
char *verb = "is";
|
char *verb = "is";
|
||||||
char *extra = "";
|
char *extra = "";
|
||||||
|
|
||||||
if (!option_bool(OPT_LOG))
|
if (!option_bool(OPT_LOG))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* build query type string if requested */
|
||||||
|
if(type > 0)
|
||||||
|
arg = querystr(arg, type);
|
||||||
|
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if ((flags & F_DNSSECOK) && option_bool(OPT_EXTRALOG))
|
||||||
|
extra = " (DNSSEC signed)";
|
||||||
|
#endif
|
||||||
|
|
||||||
name = sanitise(name);
|
name = sanitise(name);
|
||||||
|
|
||||||
if (addr)
|
if (addr)
|
||||||
{
|
{
|
||||||
|
dest = daemon->addrbuff;
|
||||||
|
|
||||||
if (flags & F_KEYTAG)
|
if (flags & F_KEYTAG)
|
||||||
sprintf(daemon->addrbuff, arg, addr->log.keytag, addr->log.algo, addr->log.digest);
|
sprintf(daemon->addrbuff, arg, addr->log.keytag, addr->log.algo, addr->log.digest);
|
||||||
else if (flags & F_RCODE)
|
else if (flags & F_RCODE)
|
||||||
@@ -1929,13 +1988,12 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
|
|||||||
sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
|
sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (flags & (F_IPV4 | F_IPV6))
|
||||||
inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
|
inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
|
||||||
addr, daemon->addrbuff, ADDRSTRLEN);
|
addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
dest = arg;
|
dest = arg;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & F_REVERSE)
|
if (flags & F_REVERSE)
|
||||||
{
|
{
|
||||||
|
|||||||
+36
-1
@@ -79,13 +79,46 @@ ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
|||||||
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
|
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* like match_netid() except that the check can have a trailing * for wildcard */
|
||||||
|
/* started as a direct copy of match_netid() */
|
||||||
|
int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool)
|
||||||
|
{
|
||||||
|
struct dhcp_netid *tmp1;
|
||||||
|
|
||||||
|
for (; check; check = check->next)
|
||||||
|
{
|
||||||
|
const int check_len = strlen(check->net);
|
||||||
|
const int is_wc = (check->net[check_len - 1] == '*');
|
||||||
|
|
||||||
|
/* '#' for not is for backwards compat. */
|
||||||
|
if (check->net[0] != '!' && check->net[0] != '#')
|
||||||
|
{
|
||||||
|
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
|
||||||
|
if (is_wc ? (strncmp(check->net, tmp1->net, check_len-1) == 0) :
|
||||||
|
(strcmp(check->net, tmp1->net) == 0))
|
||||||
|
break;
|
||||||
|
if (!tmp1)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
|
||||||
|
if (is_wc ? (strncmp((check->net)+1, tmp1->net, check_len-2) == 0) :
|
||||||
|
(strcmp((check->net)+1, tmp1->net) == 0))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
|
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
|
||||||
{
|
{
|
||||||
struct tag_if *exprs;
|
struct tag_if *exprs;
|
||||||
struct dhcp_netid_list *list;
|
struct dhcp_netid_list *list;
|
||||||
|
|
||||||
|
/* this now uses match_netid_wild() above so that tag_if can
|
||||||
|
* be used to set a 'group of interfaces' tag.
|
||||||
|
*/
|
||||||
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
|
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
|
||||||
if (match_netid(exprs->tag, tags, 1))
|
if (match_netid_wild(exprs->tag, tags))
|
||||||
for (list = exprs->set; list; list = list->next)
|
for (list = exprs->set; list; list = list->next)
|
||||||
{
|
{
|
||||||
list->list->next = tags;
|
list->list->next = tags;
|
||||||
@@ -620,6 +653,8 @@ static const struct opttab_t {
|
|||||||
{ "client-arch", 93, 2 | OT_DEC },
|
{ "client-arch", 93, 2 | OT_DEC },
|
||||||
{ "client-interface-id", 94, 0 },
|
{ "client-interface-id", 94, 0 },
|
||||||
{ "client-machine-id", 97, 0 },
|
{ "client-machine-id", 97, 0 },
|
||||||
|
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||||
|
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||||
{ "subnet-select", 118, OT_INTERNAL },
|
{ "subnet-select", 118, OT_INTERNAL },
|
||||||
{ "domain-search", 119, OT_RFC1035_NAME },
|
{ "domain-search", 119, OT_RFC1035_NAME },
|
||||||
{ "sip-server", 120, 0 },
|
{ "sip-server", 120, 0 },
|
||||||
|
|||||||
+1
-2
@@ -1245,9 +1245,8 @@ extern struct daemon {
|
|||||||
/* cache.c */
|
/* cache.c */
|
||||||
void cache_init(void);
|
void cache_init(void);
|
||||||
void next_uid(struct crec *crecp);
|
void next_uid(struct crec *crecp);
|
||||||
void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg);
|
void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, unsigned short type);
|
||||||
char *record_source(unsigned int index);
|
char *record_source(unsigned int index);
|
||||||
char *querystr(char *desc, unsigned short type);
|
|
||||||
int cache_find_non_terminal(char *name, time_t now);
|
int cache_find_non_terminal(char *name, time_t now);
|
||||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||||
union all_addr *addr, time_t now,
|
union all_addr *addr, time_t now,
|
||||||
|
|||||||
+10
-10
@@ -954,9 +954,9 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
a.log.keytag = keytag;
|
a.log.keytag = keytag;
|
||||||
a.log.algo = algo;
|
a.log.algo = algo;
|
||||||
if (algo_digest_name(algo))
|
if (algo_digest_name(algo))
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu", 0);
|
||||||
else
|
else
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu (not supported)");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu (not supported)", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -973,7 +973,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
|
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DNSKEY", 0);
|
||||||
return STAT_BOGUS | failflags;
|
return STAT_BOGUS | failflags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1012,7 +1012,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
if (STAT_ISEQUAL(rc, STAT_INSECURE))
|
if (STAT_ISEQUAL(rc, STAT_INSECURE))
|
||||||
{
|
{
|
||||||
my_syslog(LOG_WARNING, _("Insecure DS reply received for %s, check domain configuration and upstream DNS server DNSSEC support"), name);
|
my_syslog(LOG_WARNING, _("Insecure DS reply received for %s, check domain configuration and upstream DNS server DNSSEC support"), name);
|
||||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS - not secure");
|
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS - not secure", 0);
|
||||||
return STAT_BOGUS | DNSSEC_FAIL_INDET;
|
return STAT_BOGUS | DNSSEC_FAIL_INDET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,7 +1025,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
from the DS's zone, and not the parent zone. */
|
from the DS's zone, and not the parent zone. */
|
||||||
if (STAT_ISEQUAL(rc, STAT_NEED_KEY) && hostname_isequal(name, keyname))
|
if (STAT_ISEQUAL(rc, STAT_NEED_KEY) && hostname_isequal(name, keyname))
|
||||||
{
|
{
|
||||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS");
|
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "BOGUS DS", 0);
|
||||||
return STAT_BOGUS;
|
return STAT_BOGUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1081,9 +1081,9 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
a.log.algo = algo;
|
a.log.algo = algo;
|
||||||
a.log.digest = digest;
|
a.log.digest = digest;
|
||||||
if (ds_digest_name(digest) && algo_digest_name(algo))
|
if (ds_digest_name(digest) && algo_digest_name(algo))
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu", 0);
|
||||||
else
|
else
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)");
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1116,7 +1116,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
|
|
||||||
cache_end_insert();
|
cache_end_insert();
|
||||||
|
|
||||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS");
|
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
@@ -1893,7 +1893,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
|
|
||||||
/* Find all the targets we're looking for answers to.
|
/* Find all the targets we're looking for answers to.
|
||||||
The zeroth array element is for the query, subsequent ones
|
The zeroth array element is for the query, subsequent ones
|
||||||
for CNAME targets, unless the query is for a CNAME. */
|
for CNAME targets, unless the query is for a CNAME or ANY. */
|
||||||
|
|
||||||
if (!expand_workspace(&targets, &target_sz, 0))
|
if (!expand_workspace(&targets, &target_sz, 0))
|
||||||
return STAT_BOGUS;
|
return STAT_BOGUS;
|
||||||
@@ -1912,7 +1912,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
if (qtype == T_RRSIG)
|
if (qtype == T_RRSIG)
|
||||||
return STAT_INSECURE;
|
return STAT_INSECURE;
|
||||||
|
|
||||||
if (qtype != T_CNAME)
|
if (qtype != T_CNAME && qtype != T_ANY)
|
||||||
for (j = ntohs(header->ancount); j != 0; j--)
|
for (j = ntohs(header->ancount); j != 0; j--)
|
||||||
{
|
{
|
||||||
if (!(p1 = skip_name(p1, header, plen, 10)))
|
if (!(p1 = skip_name(p1, header, plen, 10)))
|
||||||
|
|||||||
+3
-3
@@ -393,7 +393,7 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
|||||||
union all_addr addr;
|
union all_addr addr;
|
||||||
|
|
||||||
if (flags & (F_NXDOMAIN | F_NOERR))
|
if (flags & (F_NXDOMAIN | F_NOERR))
|
||||||
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL);
|
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL, 0);
|
||||||
|
|
||||||
setup_reply(header, flags, ede);
|
setup_reply(header, flags, ede);
|
||||||
|
|
||||||
@@ -412,7 +412,7 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
|||||||
|
|
||||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||||
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr);
|
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr);
|
||||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL);
|
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & gotname & F_IPV6)
|
if (flags & gotname & F_IPV6)
|
||||||
@@ -427,7 +427,7 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
|||||||
|
|
||||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||||
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr);
|
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr);
|
||||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL);
|
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trunc)
|
if (trunc)
|
||||||
|
|||||||
+17
-19
@@ -119,12 +119,12 @@ static void set_outgoing_mark(struct frec *forward, int fd)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void log_query_mysockaddr(unsigned int flags, char *name, union mysockaddr *addr, char *arg)
|
static void log_query_mysockaddr(unsigned int flags, char *name, union mysockaddr *addr, char *arg, unsigned short type)
|
||||||
{
|
{
|
||||||
if (addr->sa.sa_family == AF_INET)
|
if (addr->sa.sa_family == AF_INET)
|
||||||
log_query(flags | F_IPV4, name, (union all_addr *)&addr->in.sin_addr, arg);
|
log_query(flags | F_IPV4, name, (union all_addr *)&addr->in.sin_addr, arg, type);
|
||||||
else
|
else
|
||||||
log_query(flags | F_IPV6, name, (union all_addr *)&addr->in6.sin6_addr, arg);
|
log_query(flags | F_IPV6, name, (union all_addr *)&addr->in6.sin6_addr, arg, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void server_send(struct server *server, int fd,
|
static void server_send(struct server *server, int fd,
|
||||||
@@ -138,12 +138,13 @@ static void server_send(struct server *server, int fd,
|
|||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
static void server_send_log(struct server *server, int fd,
|
static void server_send_log(struct server *server, int fd,
|
||||||
const void *header, size_t plen, int dumpflags,
|
const void *header, size_t plen, int dumpflags,
|
||||||
unsigned int logflags, char *name, char *arg)
|
unsigned int logflags, char *name, char *arg,
|
||||||
|
unsigned short type)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DUMPFILE
|
#ifdef HAVE_DUMPFILE
|
||||||
dump_packet(dumpflags, (void *)header, (size_t)plen, NULL, &server->addr);
|
dump_packet(dumpflags, (void *)header, (size_t)plen, NULL, &server->addr);
|
||||||
#endif
|
#endif
|
||||||
log_query_mysockaddr(logflags, name, &server->addr, arg);
|
log_query_mysockaddr(logflags, name, &server->addr, arg, type);
|
||||||
server_send(server, fd, header, plen, 0);
|
server_send(server, fd, header, plen, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -494,12 +495,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
if (!gotname)
|
if (!gotname)
|
||||||
strcpy(daemon->namebuff, "query");
|
strcpy(daemon->namebuff, "query");
|
||||||
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff,
|
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff,
|
||||||
&srv->addr, NULL);
|
&srv->addr, NULL, 0);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
else
|
else
|
||||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, daemon->namebuff, &srv->addr,
|
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, daemon->namebuff, &srv->addr,
|
||||||
querystr("dnssec-retry", (forward->flags & FREC_DNSKEY_QUERY) ? T_DNSKEY : T_DS));
|
"dnssec-retry", (forward->flags & FREC_DNSKEY_QUERY) ? T_DNSKEY : T_DS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
srv->queries++;
|
srv->queries++;
|
||||||
@@ -653,7 +654,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
union all_addr a;
|
union all_addr a;
|
||||||
a.log.rcode = rcode;
|
a.log.rcode = rcode;
|
||||||
a.log.ede = ede;
|
a.log.ede = ede;
|
||||||
log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL);
|
log_query(F_UPSTREAM | F_RCODE, "error", &a, NULL, 0);
|
||||||
|
|
||||||
return resize_packet(header, n, pheader, plen);
|
return resize_packet(header, n, pheader, plen);
|
||||||
}
|
}
|
||||||
@@ -889,7 +890,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
|
|||||||
#endif
|
#endif
|
||||||
server_send_log(server, fd, header, nn, DUMP_SEC_QUERY,
|
server_send_log(server, fd, header, nn, DUMP_SEC_QUERY,
|
||||||
F_NOEXTRA | F_DNSSEC, daemon->keyname,
|
F_NOEXTRA | F_DNSSEC, daemon->keyname,
|
||||||
querystr("dnssec-query", STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS));
|
"dnssec-query", STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS);
|
||||||
server->queries++;
|
server->queries++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1136,7 +1137,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
|
|||||||
domain = daemon->namebuff;
|
domain = daemon->namebuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_query(F_SECSTAT, domain, &a, result);
|
log_query(F_SECSTAT, domain, &a, result, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1202,7 +1203,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
|
|||||||
{
|
{
|
||||||
daemon->log_display_id = src->log_id;
|
daemon->log_display_id = src->log_id;
|
||||||
daemon->log_source_addr = &src->source;
|
daemon->log_source_addr = &src->source;
|
||||||
log_query(F_UPSTREAM, "query", NULL, "duplicate");
|
log_query(F_UPSTREAM, "query", NULL, "duplicate", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1509,10 +1510,8 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
struct auth_zone *zone;
|
struct auth_zone *zone;
|
||||||
#endif
|
#endif
|
||||||
char *types = querystr(auth_dns ? "auth" : "query", type);
|
|
||||||
|
|
||||||
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
|
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
|
||||||
&source_addr, types);
|
&source_addr, auth_dns ? "auth" : "query", type);
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
is_single_query = 1;
|
is_single_query = 1;
|
||||||
@@ -1808,7 +1807,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
|||||||
daemon->log_display_id = ++daemon->log_id;
|
daemon->log_display_id = ++daemon->log_id;
|
||||||
|
|
||||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, keyname, &server->addr,
|
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, keyname, &server->addr,
|
||||||
querystr("dnssec-query", STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? T_DNSKEY : T_DS));
|
"dnssec-query", STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? T_DNSKEY : T_DS);
|
||||||
|
|
||||||
new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
|
new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
|
||||||
|
|
||||||
@@ -1946,10 +1945,9 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
struct auth_zone *zone;
|
struct auth_zone *zone;
|
||||||
#endif
|
#endif
|
||||||
char *types = querystr(auth_dns ? "auth" : "query", qtype);
|
|
||||||
|
|
||||||
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
|
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
|
||||||
&peer_addr, types);
|
&peer_addr, auth_dns ? "auth" : "query", qtype);
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
is_single_query = 1;
|
is_single_query = 1;
|
||||||
@@ -2089,7 +2087,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
/* get query name again for logging - may have been overwritten */
|
/* get query name again for logging - may have been overwritten */
|
||||||
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
|
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
|
||||||
strcpy(daemon->namebuff, "query");
|
strcpy(daemon->namebuff, "query");
|
||||||
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff, &serv->addr, NULL);
|
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff, &serv->addr, NULL, 0);
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (master->flags & SERV_DO_DNSSEC))
|
if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (master->flags & SERV_DO_DNSSEC))
|
||||||
@@ -2121,7 +2119,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
domain = daemon->namebuff;
|
domain = daemon->namebuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_query(F_SECSTAT, domain, &a, result);
|
log_query(F_SECSTAT, domain, &a, result, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -76,9 +76,9 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name
|
|||||||
|
|
||||||
#else /* HAVE_DNSSEC || HAVE_CRYPTOHASH */
|
#else /* HAVE_DNSSEC || HAVE_CRYPTOHASH */
|
||||||
|
|
||||||
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
#define SHA256_BLOCK_SIZE 32 /* SHA256 outputs a 32 byte digest */
|
||||||
typedef unsigned char BYTE; // 8-bit byte
|
typedef unsigned char BYTE; /* 8-bit byte */
|
||||||
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
typedef unsigned int WORD; /* 32-bit word, change to "long" for 16-bit machines */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE data[64];
|
BYTE data[64];
|
||||||
@@ -238,7 +238,7 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
|||||||
|
|
||||||
i = ctx->datalen;
|
i = ctx->datalen;
|
||||||
|
|
||||||
// Pad whatever data is left in the buffer.
|
/* Pad whatever data is left in the buffer. */
|
||||||
if (ctx->datalen < 56)
|
if (ctx->datalen < 56)
|
||||||
{
|
{
|
||||||
ctx->data[i++] = 0x80;
|
ctx->data[i++] = 0x80;
|
||||||
@@ -254,7 +254,7 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
|||||||
memset(ctx->data, 0, 56);
|
memset(ctx->data, 0, 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append to the padding the total message's length in bits and transform.
|
/* Append to the padding the total message's length in bits and transform. */
|
||||||
ctx->bitlen += ctx->datalen * 8;
|
ctx->bitlen += ctx->datalen * 8;
|
||||||
ctx->data[63] = ctx->bitlen;
|
ctx->data[63] = ctx->bitlen;
|
||||||
ctx->data[62] = ctx->bitlen >> 8;
|
ctx->data[62] = ctx->bitlen >> 8;
|
||||||
@@ -266,8 +266,8 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
|||||||
ctx->data[56] = ctx->bitlen >> 56;
|
ctx->data[56] = ctx->bitlen >> 56;
|
||||||
sha256_transform(ctx, ctx->data);
|
sha256_transform(ctx, ctx->data);
|
||||||
|
|
||||||
// Since this implementation uses little endian byte ordering and SHA uses big endian,
|
/* Since this implementation uses little endian byte ordering and SHA uses big endian,
|
||||||
// reverse all the bytes when copying the final state to the output hash.
|
reverse all the bytes when copying the final state to the output hash. */
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||||
|
|||||||
+45
-20
@@ -2700,11 +2700,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
if ((err = parse_server(arg, &serv_addr, &source_addr, interface, &flags)))
|
if ((err = parse_server(arg, &serv_addr, &source_addr, interface, &flags)))
|
||||||
ret_err(err);
|
ret_err(err);
|
||||||
|
|
||||||
/* server=//1.2.3.4 is special. */
|
|
||||||
if (strlen(domain) == 0 && lastdomain)
|
|
||||||
flags |= SERV_FOR_NODOTS;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (servers_only && option == 'S')
|
if (servers_only && option == 'S')
|
||||||
@@ -2712,6 +2707,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
/* server=//1.2.3.4 is special. */
|
||||||
|
if (strlen(domain) == 0 && lastdomain)
|
||||||
|
flags |= SERV_FOR_NODOTS;
|
||||||
|
else
|
||||||
|
flags &= ~SERV_FOR_NODOTS;
|
||||||
|
|
||||||
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, &addr))
|
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, &addr))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
|
|
||||||
@@ -5027,15 +5028,33 @@ static int one_file(char *file, int hard_opt)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int file_filter(const struct dirent *ent)
|
||||||
|
{
|
||||||
|
size_t lenfile = strlen(ent->d_name);
|
||||||
|
|
||||||
|
/* ignore emacs backups and dotfiles */
|
||||||
|
|
||||||
|
if (lenfile == 0 ||
|
||||||
|
ent->d_name[lenfile - 1] == '~' ||
|
||||||
|
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
|
||||||
|
ent->d_name[0] == '.')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/* expand any name which is a directory */
|
/* expand any name which is a directory */
|
||||||
struct hostsfile *expand_filelist(struct hostsfile *list)
|
struct hostsfile *expand_filelist(struct hostsfile *list)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct hostsfile *ah;
|
int entcnt, n;
|
||||||
|
struct hostsfile *ah, *last, *next, **up;
|
||||||
|
struct dirent **namelist;
|
||||||
|
|
||||||
/* find largest used index */
|
/* find largest used index */
|
||||||
for (i = SRC_AH, ah = list; ah; ah = ah->next)
|
for (i = SRC_AH, ah = list; ah; ah = ah->next)
|
||||||
{
|
{
|
||||||
|
last = ah;
|
||||||
|
|
||||||
if (i <= ah->index)
|
if (i <= ah->index)
|
||||||
i = ah->index + 1;
|
i = ah->index + 1;
|
||||||
|
|
||||||
@@ -5051,46 +5070,48 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
|
|||||||
struct stat buf;
|
struct stat buf;
|
||||||
if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
|
if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
|
||||||
{
|
{
|
||||||
DIR *dir_stream;
|
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
|
|
||||||
/* don't read this as a file */
|
/* don't read this as a file */
|
||||||
ah->flags |= AH_INACTIVE;
|
ah->flags |= AH_INACTIVE;
|
||||||
|
|
||||||
if (!(dir_stream = opendir(ah->fname)))
|
entcnt = scandir(ah->fname, &namelist, file_filter, alphasort);
|
||||||
|
if (entcnt < 0)
|
||||||
my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
|
my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
|
||||||
ah->fname, strerror(errno));
|
ah->fname, strerror(errno));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while ((ent = readdir(dir_stream)))
|
for (n = 0; n < entcnt; n++)
|
||||||
{
|
{
|
||||||
|
ent = namelist[n];
|
||||||
size_t lendir = strlen(ah->fname);
|
size_t lendir = strlen(ah->fname);
|
||||||
size_t lenfile = strlen(ent->d_name);
|
size_t lenfile = strlen(ent->d_name);
|
||||||
struct hostsfile *ah1;
|
struct hostsfile *ah1;
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
/* ignore emacs backups and dotfiles */
|
|
||||||
if (lenfile == 0 ||
|
|
||||||
ent->d_name[lenfile - 1] == '~' ||
|
|
||||||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
|
|
||||||
ent->d_name[0] == '.')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* see if we have an existing record.
|
/* see if we have an existing record.
|
||||||
dir is ah->fname
|
dir is ah->fname
|
||||||
file is ent->d_name
|
file is ent->d_name
|
||||||
path to match is ah1->fname */
|
path to match is ah1->fname */
|
||||||
|
|
||||||
for (ah1 = list; ah1; ah1 = ah1->next)
|
for (up = &list, ah1 = list; ah1; ah1 = next)
|
||||||
{
|
{
|
||||||
|
next = ah1->next;
|
||||||
|
|
||||||
if (lendir < strlen(ah1->fname) &&
|
if (lendir < strlen(ah1->fname) &&
|
||||||
strstr(ah1->fname, ah->fname) == ah1->fname &&
|
strstr(ah1->fname, ah->fname) == ah1->fname &&
|
||||||
ah1->fname[lendir] == '/' &&
|
ah1->fname[lendir] == '/' &&
|
||||||
strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
|
strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
|
||||||
{
|
{
|
||||||
ah1->flags &= ~AH_INACTIVE;
|
ah1->flags &= ~AH_INACTIVE;
|
||||||
|
/* If found, remove from list to re-insert at the end.
|
||||||
|
Unless it's already at the end. */
|
||||||
|
if (last != ah1)
|
||||||
|
*up = next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
up = &ah1->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make new record */
|
/* make new record */
|
||||||
@@ -5111,17 +5132,21 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
|
|||||||
ah1->fname = path;
|
ah1->fname = path;
|
||||||
ah1->index = i++;
|
ah1->index = i++;
|
||||||
ah1->flags = AH_DIR;
|
ah1->flags = AH_DIR;
|
||||||
ah1->next = list;
|
|
||||||
list = ah1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Edge case, may be the last in the list anyway */
|
||||||
|
if (last != ah1)
|
||||||
|
last->next = ah1;
|
||||||
|
ah1->next = NULL;
|
||||||
|
last = ah1;
|
||||||
|
|
||||||
/* inactivate record if not regular file */
|
/* inactivate record if not regular file */
|
||||||
if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
|
if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
|
||||||
ah1->flags |= AH_INACTIVE;
|
ah1->flags |= AH_INACTIVE;
|
||||||
|
|
||||||
}
|
}
|
||||||
closedir(dir_stream);
|
|
||||||
}
|
}
|
||||||
|
free(namelist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+26
-26
@@ -20,13 +20,13 @@
|
|||||||
|
|
||||||
#define LOG(...) \
|
#define LOG(...) \
|
||||||
do { \
|
do { \
|
||||||
my_syslog(LOG_WARNING, __VA_ARGS__); \
|
my_syslog(LOG_DEBUG, __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ASSERT(condition) \
|
#define ASSERT(condition) \
|
||||||
do { \
|
do { \
|
||||||
if (!(condition)) \
|
if (!(condition)) \
|
||||||
LOG("[pattern.c:%d] Assertion failure: %s", __LINE__, #condition); \
|
my_syslog(LOG_ERR, _("[pattern.c:%d] Assertion failure: %s"), __LINE__, #condition); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,8 +66,8 @@ static int is_string_matching_glob_pattern(
|
|||||||
pattern_character -= 'a' - 'A';
|
pattern_character -= 'a' - 'A';
|
||||||
if (pattern_character == '*')
|
if (pattern_character == '*')
|
||||||
{
|
{
|
||||||
// zero-or-more-character wildcard
|
/* zero-or-more-character wildcard */
|
||||||
// Try to match at value_index, otherwise restart at value_index + 1 next.
|
/* Try to match at value_index, otherwise restart at value_index + 1 next. */
|
||||||
next_pattern_index = pattern_index;
|
next_pattern_index = pattern_index;
|
||||||
pattern_index++;
|
pattern_index++;
|
||||||
if (value_index < num_value_bytes)
|
if (value_index < num_value_bytes)
|
||||||
@@ -78,7 +78,7 @@ static int is_string_matching_glob_pattern(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// ordinary character
|
/* ordinary character */
|
||||||
if (value_index < num_value_bytes)
|
if (value_index < num_value_bytes)
|
||||||
{
|
{
|
||||||
char value_character = value[value_index];
|
char value_character = value[value_index];
|
||||||
@@ -139,7 +139,7 @@ int is_valid_dns_name(const char *value)
|
|||||||
(*c < 'A' || *c > 'Z') &&
|
(*c < 'A' || *c > 'Z') &&
|
||||||
(*c < 'a' || *c > 'z'))
|
(*c < 'a' || *c > 'z'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Invalid character %c.", *c);
|
LOG(_("Invalid DNS name: Invalid character %c."), *c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c)
|
if (*c)
|
||||||
@@ -148,12 +148,12 @@ int is_valid_dns_name(const char *value)
|
|||||||
{
|
{
|
||||||
if (!*c || *c == '.')
|
if (!*c || *c == '.')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Empty label.");
|
LOG(_("Invalid DNS name: Empty label."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c == '-')
|
if (*c == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Label starts with hyphen.");
|
LOG(_("Invalid DNS name: Label starts with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
label = c;
|
label = c;
|
||||||
@@ -167,13 +167,13 @@ int is_valid_dns_name(const char *value)
|
|||||||
{
|
{
|
||||||
if (c[-1] == '-')
|
if (c[-1] == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Label ends with hyphen.");
|
LOG(_("Invalid DNS name: Label ends with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t num_label_bytes = (size_t) (c - label);
|
size_t num_label_bytes = (size_t) (c - label);
|
||||||
if (num_label_bytes > 63)
|
if (num_label_bytes > 63)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Label is too long (%zu).", num_label_bytes);
|
LOG(_("Invalid DNS name: Label is too long (%zu)."), num_label_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
num_labels++;
|
num_labels++;
|
||||||
@@ -181,12 +181,12 @@ int is_valid_dns_name(const char *value)
|
|||||||
{
|
{
|
||||||
if (num_labels < 2)
|
if (num_labels < 2)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Not enough labels (%zu).", num_labels);
|
LOG(_("Invalid DNS name: Not enough labels (%zu)."), num_labels);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (is_label_numeric)
|
if (is_label_numeric)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Final label is fully numeric.");
|
LOG(_("Invalid DNS name: Final label is fully numeric."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_label_bytes == 5 &&
|
if (num_label_bytes == 5 &&
|
||||||
@@ -196,12 +196,12 @@ int is_valid_dns_name(const char *value)
|
|||||||
(label[3] == 'a' || label[3] == 'A') &&
|
(label[3] == 'a' || label[3] == 'A') &&
|
||||||
(label[4] == 'l' || label[4] == 'L'))
|
(label[4] == 'l' || label[4] == 'L'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: \"local\" pseudo-TLD.");
|
LOG(_("Invalid DNS name: \"local\" pseudo-TLD."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_bytes < 1 || num_bytes > 253)
|
if (num_bytes < 1 || num_bytes > 253)
|
||||||
{
|
{
|
||||||
LOG("DNS name has invalid length (%zu).", num_bytes);
|
LOG(_("DNS name has invalid length (%zu)."), num_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -249,13 +249,13 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
for (const char *c = value;; c++)
|
for (const char *c = value;; c++)
|
||||||
{
|
{
|
||||||
if (*c &&
|
if (*c &&
|
||||||
*c != '*' && // Wildcard.
|
*c != '*' && /* Wildcard. */
|
||||||
*c != '-' && *c != '.' &&
|
*c != '-' && *c != '.' &&
|
||||||
(*c < '0' || *c > '9') &&
|
(*c < '0' || *c > '9') &&
|
||||||
(*c < 'A' || *c > 'Z') &&
|
(*c < 'A' || *c > 'Z') &&
|
||||||
(*c < 'a' || *c > 'z'))
|
(*c < 'a' || *c > 'z'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Invalid character %c.", *c);
|
LOG(_("Invalid DNS name pattern: Invalid character %c."), *c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c && *c != '*')
|
if (*c && *c != '*')
|
||||||
@@ -264,12 +264,12 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (!*c || *c == '.')
|
if (!*c || *c == '.')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Empty label.");
|
LOG(_("Invalid DNS name pattern: Empty label."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c == '-')
|
if (*c == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Label starts with hyphen.");
|
LOG(_("Invalid DNS name pattern: Label starts with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
label = c;
|
label = c;
|
||||||
@@ -282,7 +282,7 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (num_wildcards >= 2)
|
if (num_wildcards >= 2)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Wildcard character used more than twice per label.");
|
LOG(_("Invalid DNS name pattern: Wildcard character used more than twice per label."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
num_wildcards++;
|
num_wildcards++;
|
||||||
@@ -292,13 +292,13 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (c[-1] == '-')
|
if (c[-1] == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Label ends with hyphen.");
|
LOG(_("Invalid DNS name pattern: Label ends with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t num_label_bytes = (size_t) (c - label) - num_wildcards;
|
size_t num_label_bytes = (size_t) (c - label) - num_wildcards;
|
||||||
if (num_label_bytes > 63)
|
if (num_label_bytes > 63)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Label is too long (%zu).", num_label_bytes);
|
LOG(_("Invalid DNS name pattern: Label is too long (%zu)."), num_label_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
num_labels++;
|
num_labels++;
|
||||||
@@ -306,17 +306,17 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (num_labels < 2)
|
if (num_labels < 2)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Not enough labels (%zu).", num_labels);
|
LOG(_("Invalid DNS name pattern: Not enough labels (%zu)."), num_labels);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_wildcards != 0 || previous_label_has_wildcard)
|
if (num_wildcards != 0 || previous_label_has_wildcard)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Wildcard within final two labels.");
|
LOG(_("Invalid DNS name pattern: Wildcard within final two labels."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (is_label_numeric)
|
if (is_label_numeric)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Final label is fully numeric.");
|
LOG(_("Invalid DNS name pattern: Final label is fully numeric."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_label_bytes == 5 &&
|
if (num_label_bytes == 5 &&
|
||||||
@@ -326,12 +326,12 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
(label[3] == 'a' || label[3] == 'A') &&
|
(label[3] == 'a' || label[3] == 'A') &&
|
||||||
(label[4] == 'l' || label[4] == 'L'))
|
(label[4] == 'l' || label[4] == 'L'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: \"local\" pseudo-TLD.");
|
LOG(_("Invalid DNS name pattern: \"local\" pseudo-TLD."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_bytes < 1 || num_bytes > 253)
|
if (num_bytes < 1 || num_bytes > 253)
|
||||||
{
|
{
|
||||||
LOG("DNS name pattern has invalid length after removing wildcards (%zu).", num_bytes);
|
LOG(_("DNS name pattern has invalid length after removing wildcards (%zu)."), num_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+206
-128
@@ -394,18 +394,13 @@ static int private_net6(struct in6_addr *a, int ban_localhost)
|
|||||||
((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */
|
((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name, int *doctored)
|
static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, int *doctored)
|
||||||
{
|
{
|
||||||
int i, qtype, qclass, rdlen;
|
int i, qtype, qclass, rdlen;
|
||||||
|
|
||||||
for (i = count; i != 0; i--)
|
for (i = count; i != 0; i--)
|
||||||
{
|
{
|
||||||
if (name && option_bool(OPT_LOG))
|
if (!(p = skip_name(p, header, qlen, 10)))
|
||||||
{
|
|
||||||
if (!extract_name(header, qlen, &p, name, 1, 10))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (!(p = skip_name(p, header, qlen, 10)))
|
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
@@ -444,34 +439,6 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (qtype == T_TXT && name && option_bool(OPT_LOG))
|
|
||||||
{
|
|
||||||
unsigned char *p1 = p;
|
|
||||||
if (!CHECK_LEN(header, p1, qlen, rdlen))
|
|
||||||
return 0;
|
|
||||||
while ((p1 - p) < rdlen)
|
|
||||||
{
|
|
||||||
unsigned int i, len = *p1;
|
|
||||||
unsigned char *p2 = p1;
|
|
||||||
if ((p1 + len - p) >= rdlen)
|
|
||||||
return 0; /* bad packet */
|
|
||||||
/* make counted string zero-term and sanitise */
|
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
if (!isprint((int)*(p2+1)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
*p2 = *(p2+1);
|
|
||||||
p2++;
|
|
||||||
}
|
|
||||||
*p2 = 0;
|
|
||||||
my_syslog(LOG_INFO, "reply %s is %s", name, p1);
|
|
||||||
/* restore */
|
|
||||||
memmove(p1 + 1, p1, i);
|
|
||||||
*p1 = len;
|
|
||||||
p1 += len+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ADD_RDLEN(header, p, qlen, rdlen))
|
if (!ADD_RDLEN(header, p, qlen, rdlen))
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
@@ -480,7 +447,7 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doctored)
|
static int find_soa(struct dns_header *header, size_t qlen, int *doctored)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
int qtype, qclass, rdlen;
|
int qtype, qclass, rdlen;
|
||||||
@@ -489,7 +456,7 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doc
|
|||||||
|
|
||||||
/* first move to NS section and find TTL from any SOA section */
|
/* first move to NS section and find TTL from any SOA section */
|
||||||
if (!(p = skip_questions(header, qlen)) ||
|
if (!(p = skip_questions(header, qlen)) ||
|
||||||
!(p = do_doctor(p, ntohs(header->ancount), header, qlen, name, doctored)))
|
!(p = do_doctor(p, ntohs(header->ancount), header, qlen, doctored)))
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
for (i = ntohs(header->nscount); i != 0; i--)
|
for (i = ntohs(header->nscount); i != 0; i--)
|
||||||
@@ -525,7 +492,7 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* rewrite addresses in additional section too */
|
/* rewrite addresses in additional section too */
|
||||||
if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL, doctored))
|
if (!do_doctor(p, ntohs(header->arcount), header, qlen, doctored))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!found_soa)
|
if (!found_soa)
|
||||||
@@ -534,6 +501,40 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doc
|
|||||||
return minttl;
|
return minttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print TXT reply to log */
|
||||||
|
static int print_txt(struct dns_header *header, const size_t qlen, char *name,
|
||||||
|
unsigned char *p, const int ardlen, int secflag)
|
||||||
|
{
|
||||||
|
unsigned char *p1 = p;
|
||||||
|
if (!CHECK_LEN(header, p1, qlen, ardlen))
|
||||||
|
return 0;
|
||||||
|
/* Loop over TXT payload */
|
||||||
|
while ((p1 - p) < ardlen)
|
||||||
|
{
|
||||||
|
unsigned int i, len = *p1;
|
||||||
|
unsigned char *p3 = p1;
|
||||||
|
if ((p1 + len - p) >= ardlen)
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
/* make counted string zero-term and sanitise */
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (!isprint((int)*(p3+1)))
|
||||||
|
break;
|
||||||
|
*p3 = *(p3+1);
|
||||||
|
p3++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p3 = 0;
|
||||||
|
log_query(secflag | F_FORWARD | F_UPSTREAM, name, NULL, (char*)p1, 0);
|
||||||
|
/* restore */
|
||||||
|
memmove(p1 + 1, p1, i);
|
||||||
|
*p1 = len;
|
||||||
|
p1 += len+1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Note that the following code can create CNAME chains that don't point to a real record,
|
/* Note that the following code can create CNAME chains that don't point to a real record,
|
||||||
either because of lack of memory, or lack of SOA records. These are treated by the cache code as
|
either because of lack of memory, or lack of SOA records. These are treated by the cache code as
|
||||||
expired and cleaned out that way.
|
expired and cleaned out that way.
|
||||||
@@ -543,7 +544,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
int secure, int *doctored)
|
int secure, int *doctored)
|
||||||
{
|
{
|
||||||
unsigned char *p, *p1, *endrr, *namep;
|
unsigned char *p, *p1, *endrr, *namep;
|
||||||
int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
|
int j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
|
||||||
unsigned long ttl = 0;
|
unsigned long ttl = 0;
|
||||||
union all_addr addr;
|
union all_addr addr;
|
||||||
#ifdef HAVE_IPSET
|
#ifdef HAVE_IPSET
|
||||||
@@ -551,34 +552,6 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
#else
|
#else
|
||||||
(void)ipsets; /* unused */
|
(void)ipsets; /* unused */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
cache_start_insert();
|
|
||||||
|
|
||||||
/* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
|
|
||||||
if (daemon->doctors || option_bool(OPT_LOG) || option_bool(OPT_DNSSEC_VALID))
|
|
||||||
{
|
|
||||||
searched_soa = 1;
|
|
||||||
ttl = find_soa(header, qlen, name, doctored);
|
|
||||||
|
|
||||||
if (*doctored)
|
|
||||||
{
|
|
||||||
if (secure)
|
|
||||||
return 0;
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
|
||||||
for (i = 0; i < ntohs(header->ancount); i++)
|
|
||||||
if (daemon->rr_status[i] != 0)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* go through the questions. */
|
|
||||||
p = (unsigned char *)(header+1);
|
|
||||||
|
|
||||||
for (i = ntohs(header->qdcount); i != 0; i--)
|
|
||||||
{
|
|
||||||
int found = 0, cname_count = CNAME_CHAIN;
|
int found = 0, cname_count = CNAME_CHAIN;
|
||||||
struct crec *cpp = NULL;
|
struct crec *cpp = NULL;
|
||||||
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
||||||
@@ -587,24 +560,43 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
#endif
|
#endif
|
||||||
unsigned long cttl = ULONG_MAX, attl;
|
unsigned long cttl = ULONG_MAX, attl;
|
||||||
|
|
||||||
namep = p;
|
cache_start_insert();
|
||||||
if (!extract_name(header, qlen, &p, name, 1, 4))
|
|
||||||
|
/* find_soa is needed for dns_doctor side effects, so don't call it lazily if there are any. */
|
||||||
|
if (daemon->doctors || option_bool(OPT_DNSSEC_VALID))
|
||||||
|
{
|
||||||
|
searched_soa = 1;
|
||||||
|
ttl = find_soa(header, qlen, doctored);
|
||||||
|
|
||||||
|
if (*doctored)
|
||||||
|
{
|
||||||
|
if (secure)
|
||||||
|
return 0;
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
|
if (daemon->rr_status[j] != 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namep = p = (unsigned char *)(header+1);
|
||||||
|
|
||||||
|
if (ntohs(header->qdcount) != 1 || !extract_name(header, qlen, &p, name, 1, 4))
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
GETSHORT(qclass, p);
|
GETSHORT(qclass, p);
|
||||||
|
|
||||||
if (qclass != C_IN)
|
if (qclass != C_IN)
|
||||||
continue;
|
return 0;
|
||||||
|
|
||||||
/* PTRs: we chase CNAMEs here, since we have no way to
|
/* PTRs: we chase CNAMEs here, since we have no way to
|
||||||
represent them in the cache. */
|
represent them in the cache. */
|
||||||
if (qtype == T_PTR)
|
if (qtype == T_PTR)
|
||||||
{
|
{
|
||||||
int name_encoding = in_arpa_name_2_addr(name, &addr);
|
int insert = 1, name_encoding = in_arpa_name_2_addr(name, &addr);
|
||||||
|
|
||||||
if (!name_encoding)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(flags & F_NXDOMAIN))
|
if (!(flags & F_NXDOMAIN))
|
||||||
{
|
{
|
||||||
@@ -615,15 +607,13 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
for (j = 0; j < ntohs(header->ancount); j++)
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
{
|
{
|
||||||
int secflag = 0;
|
int secflag = 0;
|
||||||
unsigned char *tmp = namep;
|
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
||||||
/* the loop body overwrites the original name, so get it back here. */
|
|
||||||
if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
|
|
||||||
!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
GETSHORT(aqtype, p1);
|
GETSHORT(aqtype, p1);
|
||||||
GETSHORT(aqclass, p1);
|
GETSHORT(aqclass, p1);
|
||||||
GETLONG(attl, p1);
|
GETLONG(attl, p1);
|
||||||
|
|
||||||
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
|
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
|
||||||
{
|
{
|
||||||
(p1) -= 4;
|
(p1) -= 4;
|
||||||
@@ -638,14 +628,12 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
|
|
||||||
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
|
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
|
||||||
{
|
{
|
||||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
|
||||||
return 0;
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j] != 0)
|
if (option_bool(OPT_DNSSEC_VALID) && !no_cache_dnssec && daemon->rr_status[j] != 0)
|
||||||
{
|
{
|
||||||
/* validated RR anywhere in CNAME chain, don't cache. */
|
/* validated RR anywhere in CNAME chain, don't cache. */
|
||||||
if (cname_short || aqtype == T_CNAME)
|
if (cname_short || aqtype == T_CNAME)
|
||||||
return 0;
|
insert = 0;
|
||||||
|
|
||||||
secflag = F_DNSSECOK;
|
secflag = F_DNSSECOK;
|
||||||
/* limit TTL based on signature. */
|
/* limit TTL based on signature. */
|
||||||
@@ -654,6 +642,12 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (aqtype == T_CNAME)
|
||||||
|
log_query(secflag | F_CNAME | F_FORWARD | F_UPSTREAM, name, NULL, NULL, 0);
|
||||||
|
|
||||||
|
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (aqtype == T_CNAME)
|
if (aqtype == T_CNAME)
|
||||||
{
|
{
|
||||||
if (!cname_count--)
|
if (!cname_count--)
|
||||||
@@ -664,8 +658,16 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
goto cname_loop;
|
goto cname_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_insert(name, &addr, C_IN, now, cttl, name_encoding | secflag | F_REVERSE);
|
|
||||||
found = 1;
|
found = 1;
|
||||||
|
|
||||||
|
if (!name_encoding)
|
||||||
|
log_query(secflag | F_FORWARD | F_UPSTREAM, name, NULL, NULL, aqtype);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_query(name_encoding | secflag | F_REVERSE | F_UPSTREAM, name, &addr, NULL, 0);
|
||||||
|
if (insert)
|
||||||
|
cache_insert(name, &addr, C_IN, now, cttl, name_encoding | secflag | F_REVERSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p1 = endrr;
|
p1 = endrr;
|
||||||
@@ -679,17 +681,24 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (!searched_soa)
|
if (!searched_soa)
|
||||||
{
|
{
|
||||||
searched_soa = 1;
|
searched_soa = 1;
|
||||||
ttl = find_soa(header, qlen, NULL, doctored);
|
ttl = find_soa(header, qlen, doctored);
|
||||||
}
|
}
|
||||||
if (ttl)
|
|
||||||
cache_insert(NULL, &addr, C_IN, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
flags |= F_NEG | (secure ? F_DNSSECOK : 0);
|
||||||
|
if (name_encoding && ttl)
|
||||||
|
{
|
||||||
|
flags |= F_REVERSE | name_encoding;
|
||||||
|
cache_insert(NULL, &addr, C_IN, now, ttl, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_query(flags | F_UPSTREAM, name, &addr, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* everything other than PTR */
|
/* everything other than PTR */
|
||||||
struct crec *newc;
|
struct crec *newc;
|
||||||
int addrlen = 0;
|
int addrlen = 0, insert = 1;
|
||||||
|
|
||||||
if (qtype == T_A)
|
if (qtype == T_A)
|
||||||
{
|
{
|
||||||
@@ -704,7 +713,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
else if (qtype == T_SRV)
|
else if (qtype == T_SRV)
|
||||||
flags |= F_SRV;
|
flags |= F_SRV;
|
||||||
else
|
else
|
||||||
continue;
|
insert = 0; /* NOTE: do not cache data from CNAME queries. */
|
||||||
|
|
||||||
cname_loop1:
|
cname_loop1:
|
||||||
if (!(p1 = skip_questions(header, qlen)))
|
if (!(p1 = skip_questions(header, qlen)))
|
||||||
@@ -728,10 +737,17 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
GETSHORT(ardlen, p1);
|
GETSHORT(ardlen, p1);
|
||||||
endrr = p1+ardlen;
|
endrr = p1+ardlen;
|
||||||
|
|
||||||
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
|
/* Not what we're looking for? */
|
||||||
|
if (aqclass != C_IN || res == 2)
|
||||||
{
|
{
|
||||||
|
p1 = endrr;
|
||||||
|
if (!CHECK_LEN(header, p1, qlen, 0))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j] != 0)
|
if (option_bool(OPT_DNSSEC_VALID) && !no_cache_dnssec && daemon->rr_status[j] != 0)
|
||||||
{
|
{
|
||||||
secflag = F_DNSSECOK;
|
secflag = F_DNSSECOK;
|
||||||
|
|
||||||
@@ -740,11 +756,16 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
attl = daemon->rr_status[j];
|
attl = daemon->rr_status[j];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (aqtype == T_CNAME)
|
if (aqtype == T_CNAME)
|
||||||
{
|
{
|
||||||
if (!cname_count--)
|
if (!cname_count--)
|
||||||
return 0; /* looped CNAMES */
|
return 0; /* looped CNAMES */
|
||||||
|
|
||||||
|
log_query(secflag | F_CNAME | F_FORWARD | F_UPSTREAM, name, NULL, NULL, 0);
|
||||||
|
|
||||||
|
if (insert)
|
||||||
|
{
|
||||||
if ((newc = cache_insert(name, NULL, C_IN, now, attl, F_CNAME | F_FORWARD | secflag)))
|
if ((newc = cache_insert(name, NULL, C_IN, now, attl, F_CNAME | F_FORWARD | secflag)))
|
||||||
{
|
{
|
||||||
newc->addr.cname.target.cache = NULL;
|
newc->addr.cname.target.cache = NULL;
|
||||||
@@ -760,12 +781,23 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
cpp = newc;
|
cpp = newc;
|
||||||
if (attl < cttl)
|
if (attl < cttl)
|
||||||
cttl = attl;
|
cttl = attl;
|
||||||
|
}
|
||||||
|
|
||||||
namep = p1;
|
namep = p1;
|
||||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (qtype != T_CNAME)
|
||||||
goto cname_loop1;
|
goto cname_loop1;
|
||||||
|
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
else if (aqtype != qtype)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (!option_bool(OPT_DNSSEC_VALID) || aqtype != T_RRSIG)
|
||||||
|
#endif
|
||||||
|
log_query(secflag | F_FORWARD | F_UPSTREAM, name, NULL, NULL, aqtype);
|
||||||
}
|
}
|
||||||
else if (!(flags & F_NXDOMAIN))
|
else if (!(flags & F_NXDOMAIN))
|
||||||
{
|
{
|
||||||
@@ -790,7 +822,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (!extract_name(header, qlen, &tmp, name, 1, 0))
|
if (!extract_name(header, qlen, &tmp, name, 1, 0))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else if (flags & (F_IPV4 | F_IPV6))
|
||||||
{
|
{
|
||||||
/* copy address into aligned storage */
|
/* copy address into aligned storage */
|
||||||
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
||||||
@@ -815,13 +847,15 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
ipsets_cur = ipsets;
|
ipsets_cur = ipsets;
|
||||||
while (*ipsets_cur)
|
while (*ipsets_cur)
|
||||||
{
|
{
|
||||||
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur);
|
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur, 0);
|
||||||
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (insert)
|
||||||
|
{
|
||||||
newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
|
newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
|
||||||
if (newc && cpp)
|
if (newc && cpp)
|
||||||
{
|
{
|
||||||
@@ -831,6 +865,14 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
}
|
}
|
||||||
cpp = NULL;
|
cpp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aqtype == T_TXT)
|
||||||
|
{
|
||||||
|
if (!print_txt(header, qlen, name, p1, ardlen, secflag))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_query(flags | F_FORWARD | secflag | F_UPSTREAM, name, &addr, NULL, aqtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
p1 = endrr;
|
p1 = endrr;
|
||||||
@@ -838,18 +880,33 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found && !option_bool(OPT_NO_NEG))
|
if (!found && (qtype != T_ANY || (flags & F_NXDOMAIN)))
|
||||||
{
|
{
|
||||||
|
if (flags & F_NXDOMAIN)
|
||||||
|
{
|
||||||
|
flags &= ~(F_IPV4 | F_IPV6 | F_SRV);
|
||||||
|
|
||||||
|
/* Can store NXDOMAIN reply to CNAME or ANY query. */
|
||||||
|
if (qtype == T_CNAME || qtype == T_ANY)
|
||||||
|
insert = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_query(F_UPSTREAM | F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0), name, NULL, NULL, 0);
|
||||||
|
|
||||||
if (!searched_soa)
|
if (!searched_soa)
|
||||||
{
|
{
|
||||||
searched_soa = 1;
|
searched_soa = 1;
|
||||||
ttl = find_soa(header, qlen, NULL, doctored);
|
ttl = find_soa(header, qlen, doctored);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no SOA to get the TTL from, but there is a CNAME
|
/* If there's no SOA to get the TTL from, but there is a CNAME
|
||||||
pointing at this, inherit its TTL */
|
pointing at this, inherit its TTL */
|
||||||
if (ttl || cpp)
|
if (insert && !option_bool(OPT_NO_NEG) && (ttl || cpp))
|
||||||
{
|
{
|
||||||
newc = cache_insert(name, NULL, C_IN, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
if (ttl == 0)
|
||||||
|
ttl = cttl;
|
||||||
|
|
||||||
|
newc = cache_insert(name, NULL, C_IN, now, ttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
||||||
if (newc && cpp)
|
if (newc && cpp)
|
||||||
{
|
{
|
||||||
next_uid(newc);
|
next_uid(newc);
|
||||||
@@ -859,7 +916,6 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't put stuff from a truncated packet into the cache.
|
/* Don't put stuff from a truncated packet into the cache.
|
||||||
Don't cache replies from non-recursive nameservers, since we may get a
|
Don't cache replies from non-recursive nameservers, since we may get a
|
||||||
@@ -1033,7 +1089,7 @@ void setup_reply(struct dns_header *header, unsigned int flags, int ede)
|
|||||||
union all_addr a;
|
union all_addr a;
|
||||||
a.log.rcode = REFUSED;
|
a.log.rcode = REFUSED;
|
||||||
a.log.ede = ede;
|
a.log.ede = ede;
|
||||||
log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
|
log_query(F_CONFIG | F_RCODE, "error", &a, NULL, 0);
|
||||||
SET_RCODE(header, REFUSED);
|
SET_RCODE(header, REFUSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1393,9 +1449,25 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
ans = 0; /* have we answered this question */
|
ans = 0; /* have we answered this question */
|
||||||
|
|
||||||
while (--count != 0 && (crecp = cache_find_by_name(NULL, name, now, F_CNAME)))
|
if (qclass == C_IN)
|
||||||
|
while (--count != 0 && (crecp = cache_find_by_name(NULL, name, now, F_CNAME | F_NXDOMAIN)))
|
||||||
{
|
{
|
||||||
char *cname_target = cache_get_cname_target(crecp);
|
char *cname_target;
|
||||||
|
|
||||||
|
if (crecp->flags & F_NXDOMAIN)
|
||||||
|
{
|
||||||
|
if (qtype == T_CNAME)
|
||||||
|
{
|
||||||
|
if (!dryrun)
|
||||||
|
log_query(crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||||
|
auth = 0;
|
||||||
|
nxdomain = 1;
|
||||||
|
ans = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cname_target = cache_get_cname_target(crecp);
|
||||||
|
|
||||||
/* If the client asked for DNSSEC don't use cached data. */
|
/* If the client asked for DNSSEC don't use cached data. */
|
||||||
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
|
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
|
||||||
@@ -1409,7 +1481,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
log_query(crecp->flags, name, NULL, record_source(crecp->uid), 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
crec_ttl(crecp, now), &nameoffset,
|
crec_ttl(crecp, now), &nameoffset,
|
||||||
T_CNAME, C_IN, "d", cname_target))
|
T_CNAME, C_IN, "d", cname_target))
|
||||||
@@ -1420,6 +1492,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
else
|
else
|
||||||
return 0; /* give up if any cached CNAME in chain can't be used for DNSSEC reasons. */
|
return 0; /* give up if any cached CNAME in chain can't be used for DNSSEC reasons. */
|
||||||
|
|
||||||
|
if (qtype == T_CNAME)
|
||||||
|
break;
|
||||||
|
|
||||||
strcpy(name, cname_target);
|
strcpy(name, cname_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,7 +1521,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
#endif
|
#endif
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
ttl, NULL,
|
ttl, NULL,
|
||||||
T_TXT, t->class, "t", t->len, t->txt))
|
T_TXT, t->class, "t", t->len, t->txt))
|
||||||
@@ -1468,7 +1543,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
addr.log.rcode = NOTIMP;
|
addr.log.rcode = NOTIMP;
|
||||||
log_query(F_CONFIG | F_RCODE, name, &addr, NULL);
|
log_query(F_CONFIG | F_RCODE, name, &addr, NULL, 0);
|
||||||
}
|
}
|
||||||
ans = 1, sec_data = 0;
|
ans = 1, sec_data = 0;
|
||||||
}
|
}
|
||||||
@@ -1486,7 +1561,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, t->class));
|
log_query(F_CONFIG | F_RRNAME, name, NULL, NULL, t->class);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->local_ttl, NULL,
|
daemon->local_ttl, NULL,
|
||||||
t->class, C_IN, "t", t->len, t->txt))
|
t->class, C_IN, "t", t->len, t->txt))
|
||||||
@@ -1542,7 +1617,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ans = 1;
|
ans = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(is_arpa | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
log_query(is_arpa | F_REVERSE | F_CONFIG, intr->name, &addr, NULL, 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->local_ttl, NULL,
|
daemon->local_ttl, NULL,
|
||||||
T_PTR, C_IN, "d", intr->name))
|
T_PTR, C_IN, "d", intr->name))
|
||||||
@@ -1555,7 +1630,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>", 0);
|
||||||
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
|
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
|
||||||
if (hostname_isequal(name, ptr->name) &&
|
if (hostname_isequal(name, ptr->name) &&
|
||||||
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
@@ -1565,7 +1640,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
|
else if (is_arpa && (crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
|
||||||
{
|
{
|
||||||
/* Don't use cache when DNSSEC data required, unless we know that
|
/* Don't use cache when DNSSEC data required, unless we know that
|
||||||
the zone is unsigned, which implies that we're doing
|
the zone is unsigned, which implies that we're doing
|
||||||
@@ -1590,7 +1665,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (crecp->flags & F_NXDOMAIN)
|
if (crecp->flags & F_NXDOMAIN)
|
||||||
nxdomain = 1;
|
nxdomain = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
|
log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1599,7 +1674,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
|
log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr,
|
||||||
record_source(crecp->uid));
|
record_source(crecp->uid), 0);
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
crec_ttl(crecp, now), NULL,
|
crec_ttl(crecp, now), NULL,
|
||||||
@@ -1616,7 +1691,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL);
|
log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL, 0);
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->local_ttl, NULL,
|
daemon->local_ttl, NULL,
|
||||||
@@ -1634,7 +1709,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
nxdomain = 1;
|
nxdomain = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
log_query(F_CONFIG | F_REVERSE | is_arpa | F_NEG | F_NXDOMAIN,
|
log_query(F_CONFIG | F_REVERSE | is_arpa | F_NEG | F_NXDOMAIN,
|
||||||
name, &addr, NULL);
|
name, &addr, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1689,7 +1764,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
gotit = 1;
|
gotit = 1;
|
||||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL, 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->local_ttl, NULL, type, C_IN,
|
daemon->local_ttl, NULL, type, C_IN,
|
||||||
type == T_A ? "4" : "6", &addrlist->addr))
|
type == T_A ? "4" : "6", &addrlist->addr))
|
||||||
@@ -1699,12 +1774,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dryrun && !gotit)
|
if (!dryrun && !gotit)
|
||||||
log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
|
log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL, 0);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, flag | (dryrun ? F_NO_RR : 0))))
|
if ((crecp = cache_find_by_name(NULL, name, now, flag | F_NXDOMAIN | (dryrun ? F_NO_RR : 0))))
|
||||||
{
|
{
|
||||||
int localise = 0;
|
int localise = 0;
|
||||||
|
|
||||||
@@ -1744,7 +1819,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (crecp->flags & F_NXDOMAIN)
|
if (crecp->flags & F_NXDOMAIN)
|
||||||
nxdomain = 1;
|
nxdomain = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
log_query(crecp->flags, name, NULL, NULL);
|
log_query(crecp->flags, name, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1762,7 +1837,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr,
|
log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr,
|
||||||
record_source(crecp->uid));
|
record_source(crecp->uid), 0);
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
crec_ttl(crecp, now), NULL, type, C_IN,
|
crec_ttl(crecp, now), NULL, type, C_IN,
|
||||||
@@ -1777,7 +1852,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ans = 1, sec_data = 0;
|
ans = 1, sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->local_ttl, NULL, type, C_IN, type == T_A ? "4" : "6", &addr))
|
daemon->local_ttl, NULL, type, C_IN, type == T_A ? "4" : "6", &addr))
|
||||||
anscount++;
|
anscount++;
|
||||||
@@ -1796,7 +1871,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||||
&offset, T_MX, C_IN, "sd", rec->weight, rec->target))
|
&offset, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||||
{
|
{
|
||||||
@@ -1814,7 +1889,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL,
|
||||||
T_MX, C_IN, "sd", 1,
|
T_MX, C_IN, "sd", 1,
|
||||||
option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
|
option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
|
||||||
@@ -1836,7 +1911,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||||
&offset, T_SRV, C_IN, "sssd",
|
&offset, T_SRV, C_IN, "sssd",
|
||||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||||
@@ -1868,27 +1943,31 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, F_SRV | (dryrun ? F_NO_RR : 0))) &&
|
if ((crecp = cache_find_by_name(NULL, name, now, F_SRV | F_NXDOMAIN | (dryrun ? F_NO_RR : 0))) &&
|
||||||
rd_bit && (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
|
rd_bit && (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
|
||||||
|
do
|
||||||
{
|
{
|
||||||
|
/* don't answer wildcard queries with data not from /etc/hosts or dhcp leases, except for NXDOMAIN */
|
||||||
|
if (qtype == T_ANY && !(crecp->flags & (F_NXDOMAIN)))
|
||||||
|
break;
|
||||||
|
|
||||||
if (!(crecp->flags & F_DNSSECOK))
|
if (!(crecp->flags & F_DNSSECOK))
|
||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
|
|
||||||
auth = 0;
|
auth = 0;
|
||||||
found = ans = 1;
|
found = ans = 1;
|
||||||
|
|
||||||
do {
|
|
||||||
if (crecp->flags & F_NEG)
|
if (crecp->flags & F_NEG)
|
||||||
{
|
{
|
||||||
if (crecp->flags & F_NXDOMAIN)
|
if (crecp->flags & F_NXDOMAIN)
|
||||||
nxdomain = 1;
|
nxdomain = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
log_query(crecp->flags, name, NULL, NULL);
|
log_query(crecp->flags, name, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
else if (!dryrun)
|
else if (!dryrun)
|
||||||
{
|
{
|
||||||
char *target = blockdata_retrieve(crecp->addr.srv.target, crecp->addr.srv.targetlen, NULL);
|
char *target = blockdata_retrieve(crecp->addr.srv.target, crecp->addr.srv.targetlen, NULL);
|
||||||
log_query(crecp->flags, name, NULL, 0);
|
log_query(crecp->flags, name, NULL, NULL, 0);
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
crec_ttl(crecp, now), NULL, T_SRV, C_IN, "sssd",
|
crec_ttl(crecp, now), NULL, T_SRV, C_IN, "sssd",
|
||||||
@@ -1898,14 +1977,13 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
} while ((crecp = cache_find_by_name(crecp, name, now, F_SRV)));
|
} while ((crecp = cache_find_by_name(crecp, name, now, F_SRV)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
|
if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
|
||||||
{
|
{
|
||||||
ans = 1;
|
ans = 1;
|
||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
log_query(F_CONFIG | F_NEG, name, NULL, NULL);
|
log_query(F_CONFIG | F_NEG, name, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1919,7 +1997,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>", 0);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
|
||||||
NULL, T_NAPTR, C_IN, "sszzzd",
|
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||||
@@ -1936,7 +2014,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ans = 1;
|
ans = 1;
|
||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
log_query(F_CONFIG | F_NEG, name, &addr, NULL);
|
log_query(F_CONFIG | F_NEG, name, &addr, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+45
-29
@@ -84,7 +84,7 @@ static void ubus_destroy(struct ubus_context *ubus)
|
|||||||
ubus_free(ubus);
|
ubus_free(ubus);
|
||||||
daemon->ubus = NULL;
|
daemon->ubus = NULL;
|
||||||
|
|
||||||
// Forces re-initialization when we're reusing the same definitions later on.
|
/* Forces re-initialization when we're reusing the same definitions later on. */
|
||||||
ubus_object.id = 0;
|
ubus_object.id = 0;
|
||||||
ubus_object_type.id = 0;
|
ubus_object_type.id = 0;
|
||||||
}
|
}
|
||||||
@@ -171,6 +171,16 @@ void check_ubus_listeners()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHECK(stmt) \
|
||||||
|
do { \
|
||||||
|
int e = (stmt); \
|
||||||
|
if (e) \
|
||||||
|
{ \
|
||||||
|
my_syslog(LOG_ERR, _("UBus command failed: %d (%s)"), e, #stmt); \
|
||||||
|
return (UBUS_STATUS_UNKNOWN_ERROR); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
struct ubus_request_data *req, const char *method,
|
struct ubus_request_data *req, const char *method,
|
||||||
struct blob_attr *msg)
|
struct blob_attr *msg)
|
||||||
@@ -181,12 +191,13 @@ static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj
|
|||||||
(void)method;
|
(void)method;
|
||||||
(void)msg;
|
(void)msg;
|
||||||
|
|
||||||
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
|
CHECK(blob_buf_init(&b, BLOBMSG_TYPE_TABLE));
|
||||||
|
|
||||||
for (i=0; i < __METRIC_MAX; i++)
|
for (i=0; i < __METRIC_MAX; i++)
|
||||||
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
|
CHECK(blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]));
|
||||||
|
|
||||||
return ubus_send_reply(ctx, req, b.head);
|
CHECK(ubus_send_reply(ctx, req, b.head));
|
||||||
|
return UBUS_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
@@ -305,66 +316,71 @@ fail:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#undef CHECK
|
||||||
|
|
||||||
|
#define CHECK(stmt) \
|
||||||
|
do { \
|
||||||
|
int e = (stmt); \
|
||||||
|
if (e) \
|
||||||
|
{ \
|
||||||
|
my_syslog(LOG_ERR, _("UBus command failed: %d (%s)"), e, #stmt); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
|
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
|
||||||
{
|
{
|
||||||
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!ubus || !ubus_object.has_subscribers)
|
if (!ubus || !ubus_object.has_subscribers)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
|
CHECK(blob_buf_init(&b, BLOBMSG_TYPE_TABLE));
|
||||||
if (mac)
|
if (mac)
|
||||||
blobmsg_add_string(&b, "mac", mac);
|
CHECK(blobmsg_add_string(&b, "mac", mac));
|
||||||
if (ip)
|
if (ip)
|
||||||
blobmsg_add_string(&b, "ip", ip);
|
CHECK(blobmsg_add_string(&b, "ip", ip));
|
||||||
if (name)
|
if (name)
|
||||||
blobmsg_add_string(&b, "name", name);
|
CHECK(blobmsg_add_string(&b, "name", name));
|
||||||
if (interface)
|
if (interface)
|
||||||
blobmsg_add_string(&b, "interface", interface);
|
CHECK(blobmsg_add_string(&b, "interface", interface));
|
||||||
|
|
||||||
ret = ubus_notify(ubus, &ubus_object, type, b.head, -1);
|
CHECK(ubus_notify(ubus, &ubus_object, type, b.head, -1));
|
||||||
if (ret)
|
|
||||||
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
void ubus_event_bcast_connmark_allowlist_refused(u32 mark, const char *name)
|
void ubus_event_bcast_connmark_allowlist_refused(u32 mark, const char *name)
|
||||||
{
|
{
|
||||||
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!ubus || !ubus_object.has_subscribers)
|
if (!ubus || !ubus_object.has_subscribers)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
blob_buf_init(&b, 0);
|
CHECK(blob_buf_init(&b, 0));
|
||||||
blobmsg_add_u32(&b, "mark", mark);
|
CHECK(blobmsg_add_u32(&b, "mark", mark));
|
||||||
blobmsg_add_string(&b, "name", name);
|
CHECK(blobmsg_add_string(&b, "name", name));
|
||||||
|
|
||||||
ret = ubus_notify(ubus, &ubus_object, "connmark-allowlist.refused", b.head, -1);
|
CHECK(ubus_notify(ubus, &ubus_object, "connmark-allowlist.refused", b.head, -1));
|
||||||
if (ret)
|
|
||||||
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ubus_event_bcast_connmark_allowlist_resolved(u32 mark, const char *name, const char *value, u32 ttl)
|
void ubus_event_bcast_connmark_allowlist_resolved(u32 mark, const char *name, const char *value, u32 ttl)
|
||||||
{
|
{
|
||||||
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!ubus || !ubus_object.has_subscribers)
|
if (!ubus || !ubus_object.has_subscribers)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
blob_buf_init(&b, 0);
|
CHECK(blob_buf_init(&b, 0));
|
||||||
blobmsg_add_u32(&b, "mark", mark);
|
CHECK(blobmsg_add_u32(&b, "mark", mark));
|
||||||
blobmsg_add_string(&b, "name", name);
|
CHECK(blobmsg_add_string(&b, "name", name));
|
||||||
blobmsg_add_string(&b, "value", value);
|
CHECK(blobmsg_add_string(&b, "value", value));
|
||||||
blobmsg_add_u32(&b, "ttl", ttl);
|
CHECK(blobmsg_add_u32(&b, "ttl", ttl));
|
||||||
|
|
||||||
ret = ubus_notify(ubus, &ubus_object, "connmark-allowlist.resolved", b.head, /* timeout: */ 1000);
|
/* Set timeout to allow UBus subscriber to configure firewall rules before returning. */
|
||||||
if (ret)
|
CHECK(ubus_notify(ubus, &ubus_object, "connmark-allowlist.resolved", b.head, /* timeout: */ 1000));
|
||||||
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#undef CHECK
|
||||||
|
|
||||||
#endif /* HAVE_UBUS */
|
#endif /* HAVE_UBUS */
|
||||||
+30
-8
@@ -115,7 +115,8 @@ u64 rand64(void)
|
|||||||
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns 2 if names is OK but contains one or more underscores */
|
/* returns 1 if name is OK and ascii printable
|
||||||
|
* returns 2 if name should be processed by IDN */
|
||||||
static int check_name(char *in)
|
static int check_name(char *in)
|
||||||
{
|
{
|
||||||
/* remove trailing .
|
/* remove trailing .
|
||||||
@@ -123,7 +124,9 @@ static int check_name(char *in)
|
|||||||
size_t dotgap = 0, l = strlen(in);
|
size_t dotgap = 0, l = strlen(in);
|
||||||
char c;
|
char c;
|
||||||
int nowhite = 0;
|
int nowhite = 0;
|
||||||
|
int idn_encode = 0;
|
||||||
int hasuscore = 0;
|
int hasuscore = 0;
|
||||||
|
int hasucase = 0;
|
||||||
|
|
||||||
if (l == 0 || l > MAXDNAME) return 0;
|
if (l == 0 || l > MAXDNAME) return 0;
|
||||||
|
|
||||||
@@ -142,22 +145,43 @@ static int check_name(char *in)
|
|||||||
else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))
|
else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))
|
||||||
/* iscntrl only gives expected results for ascii */
|
/* iscntrl only gives expected results for ascii */
|
||||||
return 0;
|
return 0;
|
||||||
#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2)
|
|
||||||
else if (!isascii((unsigned char)c))
|
else if (!isascii((unsigned char)c))
|
||||||
|
#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2)
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
idn_encode = 1;
|
||||||
#endif
|
#endif
|
||||||
else if (c != ' ')
|
else if (c != ' ')
|
||||||
{
|
{
|
||||||
nowhite = 1;
|
nowhite = 1;
|
||||||
|
#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
|
||||||
if (c == '_')
|
if (c == '_')
|
||||||
hasuscore = 1;
|
hasuscore = 1;
|
||||||
|
#else
|
||||||
|
(void)hasuscore;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
||||||
|
if (c >= 'A' && c <= 'Z')
|
||||||
|
hasucase = 1;
|
||||||
|
#else
|
||||||
|
(void)hasucase;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nowhite)
|
if (!nowhite)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return hasuscore ? 2 : 1;
|
#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
|
||||||
|
/* Older libidn2 strips underscores, so don't do IDN processing
|
||||||
|
if the name has an underscore unless it also has non-ascii characters. */
|
||||||
|
idn_encode = idn_encode || (hasucase && !hasuscore);
|
||||||
|
#else
|
||||||
|
idn_encode = idn_encode || hasucase;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (idn_encode) ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hostnames have a more limited valid charset than domain names
|
/* Hostnames have a more limited valid charset than domain names
|
||||||
@@ -204,12 +228,8 @@ char *canonicalise(char *in, int *nomem)
|
|||||||
if (!(rc = check_name(in)))
|
if (!(rc = check_name(in)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
|
|
||||||
/* older libidn2 strips underscores, so don't do IDN processing
|
|
||||||
if the name has an underscore (check_name() returned 2) */
|
|
||||||
if (rc != 2)
|
|
||||||
#endif
|
|
||||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
||||||
|
if (rc == 2)
|
||||||
{
|
{
|
||||||
# ifdef HAVE_LIBIDN2
|
# ifdef HAVE_LIBIDN2
|
||||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
||||||
@@ -234,6 +254,8 @@ char *canonicalise(char *in, int *nomem)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
(void)rc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((ret = whine_malloc(strlen(in)+1)))
|
if ((ret = whine_malloc(strlen(in)+1)))
|
||||||
|
|||||||
Reference in new issue
Block a user