Compare commits

..
25 Commits
Author SHA1 Message Date
Dominik DL6ER e0ce3c12f2 Add all current RR types to the table of type names used for query logging.
This patch also changes the method of calling querystr() such that
it is only called when logging is enabled, to eliminate any
possible performance problems from searching the larger table.
2021-09-10 23:13:53 +01:00
Gustaf Ullberg 93cf516bf1 check_name() determines if IDN processing is needed.
Optimization that only runs IDN processing if it would alter the domain
name (non-ascii or uppercase characters).

This patch has conributions from Petr Menšík.
2021-09-10 00:13:39 +01:00
Simon Kelley 6f4de018af Revert "Skip ascii-only names IDN processing"
This reverts commit 9cb7f8a655.
2021-09-10 00:02:11 +01:00
Simon Kelley 6e91cf3172 Bump version in Debian changelog. 2021-09-08 23:19:08 +01:00
Petr Menšík 9cb7f8a655 Skip ascii-only names IDN processing
Calls to libidn on names without with only a-z A-Z - _ 0-9
have no effect, but are slow. This change elides those calls.

Patch inspire by analysis and an earlier patch from
Gustaf Ullberg <gustaf.ullberg@gmail.com>
2021-09-08 23:08:21 +01:00
Simon Kelley 5d8d1ad14b Merge branch 'nxdomain' 2021-09-08 23:05:35 +01:00
Simon Kelley cac9ca38f6 Treat ANY queries the same as CNAME queries WRT to DNSSEC on CNAME targets. 2021-09-08 21:21:22 +01:00
Simon Kelley c4523639d5 Treat ANY queries the same as CNAME queries WRT to DNSSEC on CNAME targets. 2021-09-08 21:19:15 +01:00
Simon Kelley 1ce1c6beae Caching cleanup. Use cached NXDOMAIN to answer queries of any type. 2021-09-05 18:47:45 +01:00
DL6ER 51d56df7a3 Add RFC 4833 DHCP options "posix-timezone" and "tzdb-timezone".
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-09-04 22:24:14 +01:00
Simon Kelley 860a9a57d6 Get logging of DNSSEC status right when Checking Disabled bit set. 2021-09-02 10:07:08 +01:00
Dominik DL6ER c83e33d608 Final logging tweaks. 2021-09-01 21:19:47 +01:00
Simon Kelley 7b80c75d9d Rationalise query-reply logging.
Try and log exactly what was returned, rather than just what
got cached. Also give validation status of RRsets if extra logging specified.

This commit also fixes a long-standing bug in caching of CNAME chains
leading to a PTR record.

Based on and inspired by a patch from Dominik DL6ER <dl6er@dl6er.de>
2021-08-31 18:23:03 +01:00
Geoff Back 79337f99ae Support limited wildcards in the input tags for --tag-if. 2021-08-29 13:27:27 +01:00
Geert Stappers via Dnsmasq-discuss a42ee397f3 Man page BNF error fix.
Move dhcp-range bracket indicating option.

There should already be an end-address or mode  when adding a netmask.

Also the date bumped.

Signed-off-by: Geert Stappers <stappers@stappers.nl>
2021-08-25 14:32:43 +01:00
Simon Kelley e58f8bb8c1 Merge message changes into I18N files. 2021-08-25 14:11:42 +01:00
Dominik DL6ER 58cf958e41 Fix empty domain in server option parsing when more than one domain is given
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-08-25 14:09:40 +01:00
Etan Kissling 06d01f7ae4 Make comment style consistent.
Majority of code base does not use C90-style // end of line comments.
This formats the few existing exceptions using /* */ for consistency.
2021-08-12 17:02:45 +01:00
Etan Kissling 1a33eec0ba Adjust logging levels for connmark patterns.
This brings the log levels emitted by connmark pattern code in line with
the rest of the code base. LOG_DEBUG is used for diagnostics that may be
verbose depending on the request patterns. LOG_ERR is used for problems
with the implementation itself.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:02:24 +01:00
Etan Kissling 82de7a1e96 Re-order UBus teardown logic.
When destroying the UBus context, private fields of our ubus_object were
being reset to 0 while UBus was still owning those objects. While this
seems to work out fine, it seems cleaner to first release the object so
that UBus no longer owns it, before proceding to reset those fields.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:02:07 +01:00
Etan Kissling 8e9bde57c5 Eliminate redundant UBus notify variable.
There was a `notify` variable to keep track whether a subscriber is
observing our UBus object. However, it was not properly cleaned up in
`ubus_destroy`, potentially becoming stale over UBus reconnections.
The variable was removed and the current state is examined when sending
notifications, similarly as is done in other existing OpenWrt code.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:01:17 +01:00
Etan Kissling 1bb70e08be Handle UBus serialization errors.
The various blob / blobmsg commands can fail, e.g., when memory is low.
Previously, those errors were silently discarded. This patch adds checks
for the error conditions, logging them and exiting from the functions.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:00:18 +01:00
Simon Kelley 9afcb7ae61 Revert "There was a notify variable to keep track whether a subscriber is"
This reverts commit ea43234c86.
2021-08-12 17:00:10 +01:00
Simon Kelley 545c4955e6 Revert "Re-order UBus teardown logic."
This reverts commit d387f8f06c.
2021-08-12 16:58:30 +01:00
Simon Kelley 2f2d59b35c Define order of reading files when --addn-hosts given a directory.
Also applies to --dhcp-hostsfile and --dhcp-optsfile though it is
less useful there.
2021-08-12 16:48:54 +01:00
26 changed files with 7629 additions and 5770 deletions

No files matched your search

+9
View File
@@ -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
+6
View File
@@ -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
View File
@@ -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
+671 -512
View File
File diff suppressed because it is too large. Load diff
+687 -522
View File
File diff suppressed because it is too large. Load diff
+729 -577
View File
File diff suppressed because it is too large. Load diff
+688 -523
View File
File diff suppressed because it is too large. Load diff
+696 -528
View File
File diff suppressed because it is too large. Load diff
+729 -577
View File
File diff suppressed because it is too large. Load diff
+715 -552
View File
File diff suppressed because it is too large. Load diff
+688 -522
View File
File diff suppressed because it is too large. Load diff
+729 -577
View File
File diff suppressed because it is too large. Load diff
+715 -552
View File
File diff suppressed because it is too large. Load diff
+20 -20
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+7 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)))