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 7873 additions and 6014 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
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
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
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
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
* 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
dnsmasq \- A lightweight DHCP and caching DNS server.
.SH SYNOPSIS
@@ -55,7 +55,8 @@ Don't read the hostnames in /etc/hosts.
.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
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
.B --hostsdir=<path>
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
.B --query-port.
.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
.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
.B --dhcp-hostsfile=<path>
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
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:
@@ -1173,7 +1174,7 @@ the file will be re-read when dnsmasq receives SIGHUP.
.TP
.B --dhcp-optsfile=<path>
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
\fB--dhcp-optsfile\fP will be re-read when dnsmasq receives SIGHUP. Note that
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.
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
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
.B --dhcp-optsdir=<path>
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
.B --tag-if,
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
.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
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
+689 -524
View File
File diff suppressed because it is too large. Load diff
+731 -579
View File
File diff suppressed because it is too large. Load diff
+690 -525
View File
File diff suppressed because it is too large. Load diff
+698 -530
View File
File diff suppressed because it is too large. Load diff
+731 -579
View File
File diff suppressed because it is too large. Load diff
+717 -554
View File
File diff suppressed because it is too large. Load diff
+690 -524
View File
File diff suppressed because it is too large. Load diff
+731 -579
View File
File diff suppressed because it is too large. Load diff
+717 -554
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))
{
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,
daemon->auth_ttl, NULL,
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, 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;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
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)))
{
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;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
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)))
{
log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL);
log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL, 0);
found = 1;
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)
nxdomain = 0;
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;
}
@@ -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)
{
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,
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
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)
{
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,
NULL, T_SRV, C_IN, "sssd",
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)
{
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,
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
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)
{
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,
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
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)
{
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,
NULL, T_NAPTR, C_IN, "sszzzd",
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;
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,
daemon->auth_ttl, NULL, qtype, C_IN,
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;
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,
daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
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 */
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)
{
@@ -471,14 +471,14 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
axfr = 1;
found = 1;
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)
{
auth = 1;
ns = 1; /* inhibits auth section */
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))))
{
*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 */
found = 1;
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;
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;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
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)
{
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
log_query(F_CONFIG | F_CNAME, name, NULL, NULL, 0);
strcpy(name, candidate->target);
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))
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);
addr.log.rcode = REFUSED;
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);
}
+108 -50
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);
/* 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 {
unsigned int type;
const char * const name;
} typestr[] = {
{ 1, "A" },
{ 2, "NS" },
{ 5, "CNAME" },
{ 6, "SOA" },
{ 10, "NULL" },
{ 11, "WKS" },
{ 12, "PTR" },
{ 13, "HINFO" },
{ 15, "MX" },
{ 16, "TXT" },
{ 22, "NSAP" },
{ 23, "NSAP_PTR" },
{ 24, "SIG" },
{ 25, "KEY" },
{ 28, "AAAA" },
{ 29, "LOC" },
{ 33, "SRV" },
{ 35, "NAPTR" },
{ 36, "KX" },
{ 37, "CERT" },
{ 38, "A6" },
{ 39, "DNAME" },
{ 41, "OPT" },
{ 43, "DS" },
{ 46, "RRSIG" },
{ 47, "NSEC" },
{ 48, "DNSKEY" },
{ 50, "NSEC3" },
{ 51, "NSEC3PARAM" },
{ 52, "TLSA" },
{ 53, "SMIMEA" },
{ 55, "HIP" },
{ 249, "TKEY" },
{ 250, "TSIG" },
{ 251, "IXFR" },
{ 252, "AXFR" },
{ 253, "MAILB" },
{ 254, "MAILA" },
{ 255, "ANY" },
{ 257, "CAA" }
{ 1, "A" }, /* a host address [RFC1035] */
{ 2, "NS" }, /* an authoritative name server [RFC1035] */
{ 3, "MD" }, /* a mail destination (OBSOLETE - use MX) [RFC1035] */
{ 4, "MF" }, /* a mail forwarder (OBSOLETE - use MX) [RFC1035] */
{ 5, "CNAME" }, /* the canonical name for an alias [RFC1035] */
{ 6, "SOA" }, /* marks the start of a zone of authority [RFC1035] */
{ 7, "MB" }, /* a mailbox domain name (EXPERIMENTAL) [RFC1035] */
{ 8, "MG" }, /* a mail group member (EXPERIMENTAL) [RFC1035] */
{ 9, "MR" }, /* a mail rename domain name (EXPERIMENTAL) [RFC1035] */
{ 10, "NULL" }, /* a null RR (EXPERIMENTAL) [RFC1035] */
{ 11, "WKS" }, /* a well known service description [RFC1035] */
{ 12, "PTR" }, /* a domain name pointer [RFC1035] */
{ 13, "HINFO" }, /* host information [RFC1035] */
{ 14, "MINFO" }, /* mailbox or mail list information [RFC1035] */
{ 15, "MX" }, /* mail exchange [RFC1035] */
{ 16, "TXT" }, /* text strings [RFC1035] */
{ 17, "RP" }, /* for Responsible Person [RFC1183] */
{ 18, "AFSDB" }, /* for AFS Data Base location [RFC1183][RFC5864] */
{ 19, "X25" }, /* for X.25 PSDN address [RFC1183] */
{ 20, "ISDN" }, /* for ISDN address [RFC1183] */
{ 21, "RT" }, /* for Route Through [RFC1183] */
{ 22, "NSAP" }, /* for NSAP address, NSAP style A record [RFC1706] */
{ 23, "NSAP_PTR" }, /* for domain name pointer, NSAP style [RFC1348][RFC1637][RFC1706] */
{ 24, "SIG" }, /* for security signature [RFC2535][RFC2536][RFC2537][RFC2931][RFC3008][RFC3110][RFC3755][RFC4034] */
{ 25, "KEY" }, /* for security key [RFC2535][RFC2536][RFC2537][RFC2539][RFC3008][RFC3110][RFC3755][RFC4034] */
{ 26, "PX" }, /* X.400 mail mapping information [RFC2163] */
{ 27, "GPOS" }, /* Geographical Position [RFC1712] */
{ 28, "AAAA" }, /* IP6 Address [RFC3596] */
{ 29, "LOC" }, /* Location Information [RFC1876] */
{ 30, "NXT" }, /* Next Domain (OBSOLETE) [RFC2535][RFC3755] */
{ 31, "EID" }, /* Endpoint Identifier [Michael_Patton][http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt] 1995-06*/
{ 32, "NIMLOC" }, /* Nimrod Locator [1][Michael_Patton][http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt] 1995-06*/
{ 33, "SRV" }, /* Server Selection [1][RFC2782] */
{ 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.] */
{ 35, "NAPTR" }, /* Naming Authority Pointer [RFC2168][RFC2915][RFC3403] */
{ 36, "KX" }, /* Key Exchanger [RFC2230] */
{ 37, "CERT" }, /* CERT [RFC4398] */
{ 38, "A6" }, /* A6 (OBSOLETE - use AAAA) [RFC2874][RFC3226][RFC6563] */
{ 39, "DNAME" }, /* DNAME [RFC6672] */
{ 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);
@@ -488,8 +538,6 @@ struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class
else
#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)
ttl = daemon->max_cache_ttl;
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
@@ -1807,7 +1855,7 @@ char *record_source(unsigned int index)
return "<unknown>";
}
char *querystr(char *desc, unsigned short type)
static char *querystr(char *desc, unsigned short type)
{
unsigned int i;
int len = 10; /* strlen("type=xxxxx") */
@@ -1855,7 +1903,7 @@ char *querystr(char *desc, unsigned short type)
if (types)
sprintf(buff, "<%s>", types);
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 *extra = "";
if (!option_bool(OPT_LOG))
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);
if (addr)
{
dest = daemon->addrbuff;
if (flags & F_KEYTAG)
sprintf(daemon->addrbuff, arg, addr->log.keytag, addr->log.algo, addr->log.digest);
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));
}
}
else
else if (flags & (F_IPV4 | F_IPV6))
inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
addr, daemon->addrbuff, ADDRSTRLEN);
else
dest = arg;
}
else
dest = arg;
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;
}
/* 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 tag_if *exprs;
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)
if (match_netid(exprs->tag, tags, 1))
if (match_netid_wild(exprs->tag, tags))
for (list = exprs->set; list; list = list->next)
{
list->list->next = tags;
@@ -620,6 +653,8 @@ static const struct opttab_t {
{ "client-arch", 93, 2 | OT_DEC },
{ "client-interface-id", 94, 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 },
{ "domain-search", 119, OT_RFC1035_NAME },
{ "sip-server", 120, 0 },
+1 -2
View File
@@ -1245,9 +1245,8 @@ extern struct daemon {
/* cache.c */
void cache_init(void);
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 *querystr(char *desc, unsigned short type);
int cache_find_non_terminal(char *name, time_t now);
struct crec *cache_find_by_addr(struct crec *crecp,
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.algo = 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
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;
}
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;
}
@@ -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))
{
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;
}
@@ -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. */
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;
}
@@ -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.digest = digest;
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
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();
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;
@@ -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.
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))
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)
return STAT_INSECURE;
if (qtype != T_CNAME)
if (qtype != T_CNAME && qtype != T_ANY)
for (j = ntohs(header->ancount); j != 0; j--)
{
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;
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);
@@ -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);
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)
@@ -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);
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)
+19 -21
View File
@@ -119,12 +119,12 @@ static void set_outgoing_mark(struct frec *forward, int fd)
}
#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)
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
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,
@@ -138,12 +138,13 @@ static void server_send(struct server *server, int fd,
#ifdef HAVE_DNSSEC
static void server_send_log(struct server *server, int fd,
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
dump_packet(dumpflags, (void *)header, (size_t)plen, NULL, &server->addr);
#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);
}
#endif
@@ -494,12 +495,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (!gotname)
strcpy(daemon->namebuff, "query");
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff,
&srv->addr, NULL);
&srv->addr, NULL, 0);
}
#ifdef HAVE_DNSSEC
else
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
srv->queries++;
@@ -653,7 +654,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
union all_addr a;
a.log.rcode = rcode;
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);
}
@@ -889,7 +890,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
#endif
server_send_log(server, fd, header, nn, DUMP_SEC_QUERY,
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++;
}
@@ -1136,7 +1137,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
domain = daemon->namebuff;
}
log_query(F_SECSTAT, domain, &a, result);
log_query(F_SECSTAT, domain, &a, result, 0);
}
}
#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_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
struct auth_zone *zone;
#endif
char *types = querystr(auth_dns ? "auth" : "query", type);
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
&source_addr, types);
&source_addr, auth_dns ? "auth" : "query", type);
#ifdef HAVE_CONNTRACK
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;
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);
@@ -1946,11 +1945,10 @@ unsigned char *tcp_request(int confd, time_t now,
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
char *types = querystr(auth_dns ? "auth" : "query", qtype);
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
&peer_addr, types);
&peer_addr, auth_dns ? "auth" : "query", qtype);
#ifdef HAVE_CONNTRACK
is_single_query = 1;
#endif
@@ -2089,7 +2087,7 @@ unsigned char *tcp_request(int confd, time_t now,
/* get query name again for logging - may have been overwritten */
if (!(gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
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
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;
}
log_query(F_SECSTAT, domain, &a, result);
log_query(F_SECSTAT, domain, &a, result, 0);
}
#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 */
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
typedef unsigned char BYTE; // 8-bit byte
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
#define SHA256_BLOCK_SIZE 32 /* SHA256 outputs a 32 byte digest */
typedef unsigned char BYTE; /* 8-bit byte */
typedef unsigned int WORD; /* 32-bit word, change to "long" for 16-bit machines */
typedef struct {
BYTE data[64];
@@ -238,7 +238,7 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
i = ctx->datalen;
// Pad whatever data is left in the buffer.
/* Pad whatever data is left in the buffer. */
if (ctx->datalen < 56)
{
ctx->data[i++] = 0x80;
@@ -254,7 +254,7 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
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->data[63] = ctx->bitlen;
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;
sha256_transform(ctx, ctx->data);
// 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.
/* 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. */
for (i = 0; i < 4; ++i)
{
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)))
ret_err(err);
/* server=//1.2.3.4 is special. */
if (strlen(domain) == 0 && lastdomain)
flags |= SERV_FOR_NODOTS;
}
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)
{
/* 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))
ret_err(gen_err);
@@ -5027,15 +5028,33 @@ static int one_file(char *file, int hard_opt)
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 */
struct hostsfile *expand_filelist(struct hostsfile *list)
{
unsigned int i;
struct hostsfile *ah;
int entcnt, n;
struct hostsfile *ah, *last, *next, **up;
struct dirent **namelist;
/* find largest used index */
for (i = SRC_AH, ah = list; ah; ah = ah->next)
{
last = ah;
if (i <= ah->index)
i = ah->index + 1;
@@ -5051,46 +5070,48 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
struct stat buf;
if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
{
DIR *dir_stream;
struct dirent *ent;
/* don't read this as a file */
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"),
ah->fname, strerror(errno));
else
{
while ((ent = readdir(dir_stream)))
for (n = 0; n < entcnt; n++)
{
ent = namelist[n];
size_t lendir = strlen(ah->fname);
size_t lenfile = strlen(ent->d_name);
struct hostsfile *ah1;
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.
dir is ah->fname
file is ent->d_name
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) &&
strstr(ah1->fname, ah->fname) == ah1->fname &&
ah1->fname[lendir] == '/' &&
strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
{
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;
}
up = &ah1->next;
}
/* make new record */
@@ -5111,17 +5132,21 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
ah1->fname = path;
ah1->index = i++;
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 */
if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
ah1->flags |= AH_INACTIVE;
}
closedir(dir_stream);
}
free(namelist);
}
}
+26 -26
View File
@@ -20,13 +20,13 @@
#define LOG(...) \
do { \
my_syslog(LOG_WARNING, __VA_ARGS__); \
my_syslog(LOG_DEBUG, __VA_ARGS__); \
} while (0)
#define ASSERT(condition) \
do { \
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)
/**
@@ -66,8 +66,8 @@ static int is_string_matching_glob_pattern(
pattern_character -= 'a' - 'A';
if (pattern_character == '*')
{
// zero-or-more-character wildcard
// Try to match at value_index, otherwise restart at value_index + 1 next.
/* zero-or-more-character wildcard */
/* Try to match at value_index, otherwise restart at value_index + 1 next. */
next_pattern_index = pattern_index;
pattern_index++;
if (value_index < num_value_bytes)
@@ -78,7 +78,7 @@ static int is_string_matching_glob_pattern(
}
else
{
// ordinary character
/* ordinary character */
if (value_index < num_value_bytes)
{
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'))
{
LOG("Invalid DNS name: Invalid character %c.", *c);
LOG(_("Invalid DNS name: Invalid character %c."), *c);
return 0;
}
if (*c)
@@ -148,12 +148,12 @@ int is_valid_dns_name(const char *value)
{
if (!*c || *c == '.')
{
LOG("Invalid DNS name: Empty label.");
LOG(_("Invalid DNS name: Empty label."));
return 0;
}
if (*c == '-')
{
LOG("Invalid DNS name: Label starts with hyphen.");
LOG(_("Invalid DNS name: Label starts with hyphen."));
return 0;
}
label = c;
@@ -167,13 +167,13 @@ int is_valid_dns_name(const char *value)
{
if (c[-1] == '-')
{
LOG("Invalid DNS name: Label ends with hyphen.");
LOG(_("Invalid DNS name: Label ends with hyphen."));
return 0;
}
size_t num_label_bytes = (size_t) (c - label);
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;
}
num_labels++;
@@ -181,12 +181,12 @@ int is_valid_dns_name(const char *value)
{
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;
}
if (is_label_numeric)
{
LOG("Invalid DNS name: Final label is fully numeric.");
LOG(_("Invalid DNS name: Final label is fully numeric."));
return 0;
}
if (num_label_bytes == 5 &&
@@ -196,12 +196,12 @@ int is_valid_dns_name(const char *value)
(label[3] == 'a' || label[3] == 'A') &&
(label[4] == 'l' || label[4] == 'L'))
{
LOG("Invalid DNS name: \"local\" pseudo-TLD.");
LOG(_("Invalid DNS name: \"local\" pseudo-TLD."));
return 0;
}
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 1;
@@ -249,13 +249,13 @@ int is_valid_dns_name_pattern(const char *value)
for (const char *c = value;; c++)
{
if (*c &&
*c != '*' && // Wildcard.
*c != '*' && /* Wildcard. */
*c != '-' && *c != '.' &&
(*c < '0' || *c > '9') &&
(*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;
}
if (*c && *c != '*')
@@ -264,12 +264,12 @@ int is_valid_dns_name_pattern(const char *value)
{
if (!*c || *c == '.')
{
LOG("Invalid DNS name pattern: Empty label.");
LOG(_("Invalid DNS name pattern: Empty label."));
return 0;
}
if (*c == '-')
{
LOG("Invalid DNS name pattern: Label starts with hyphen.");
LOG(_("Invalid DNS name pattern: Label starts with hyphen."));
return 0;
}
label = c;
@@ -282,7 +282,7 @@ int is_valid_dns_name_pattern(const char *value)
{
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;
}
num_wildcards++;
@@ -292,13 +292,13 @@ int is_valid_dns_name_pattern(const char *value)
{
if (c[-1] == '-')
{
LOG("Invalid DNS name pattern: Label ends with hyphen.");
LOG(_("Invalid DNS name pattern: Label ends with hyphen."));
return 0;
}
size_t num_label_bytes = (size_t) (c - label) - num_wildcards;
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;
}
num_labels++;
@@ -306,17 +306,17 @@ int is_valid_dns_name_pattern(const char *value)
{
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;
}
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;
}
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;
}
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[4] == 'l' || label[4] == 'L'))
{
LOG("Invalid DNS name pattern: \"local\" pseudo-TLD.");
LOG(_("Invalid DNS name pattern: \"local\" pseudo-TLD."));
return 0;
}
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 1;
+418 -340
View File
File diff suppressed because it is too large. Load diff
+45 -29
View File
@@ -84,7 +84,7 @@ static void ubus_destroy(struct ubus_context *ubus)
ubus_free(ubus);
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_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,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
@@ -181,12 +191,13 @@ static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj
(void)method;
(void)msg;
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
CHECK(blob_buf_init(&b, BLOBMSG_TYPE_TABLE));
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
@@ -305,66 +316,71 @@ fail:
}
#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)
{
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
int ret;
if (!ubus || !ubus_object.has_subscribers)
return;
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
CHECK(blob_buf_init(&b, BLOBMSG_TYPE_TABLE));
if (mac)
blobmsg_add_string(&b, "mac", mac);
CHECK(blobmsg_add_string(&b, "mac", mac));
if (ip)
blobmsg_add_string(&b, "ip", ip);
CHECK(blobmsg_add_string(&b, "ip", ip));
if (name)
blobmsg_add_string(&b, "name", name);
CHECK(blobmsg_add_string(&b, "name", name));
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);
if (ret)
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
CHECK(ubus_notify(ubus, &ubus_object, type, b.head, -1));
}
#ifdef HAVE_CONNTRACK
void ubus_event_bcast_connmark_allowlist_refused(u32 mark, const char *name)
{
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
int ret;
if (!ubus || !ubus_object.has_subscribers)
return;
blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "mark", mark);
blobmsg_add_string(&b, "name", name);
CHECK(blob_buf_init(&b, 0));
CHECK(blobmsg_add_u32(&b, "mark", mark));
CHECK(blobmsg_add_string(&b, "name", name));
ret = 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));
CHECK(ubus_notify(ubus, &ubus_object, "connmark-allowlist.refused", b.head, -1));
}
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;
int ret;
if (!ubus || !ubus_object.has_subscribers)
return;
blob_buf_init(&b, 0);
blobmsg_add_u32(&b, "mark", mark);
blobmsg_add_string(&b, "name", name);
blobmsg_add_string(&b, "value", value);
blobmsg_add_u32(&b, "ttl", ttl);
CHECK(blob_buf_init(&b, 0));
CHECK(blobmsg_add_u32(&b, "mark", mark));
CHECK(blobmsg_add_string(&b, "name", name));
CHECK(blobmsg_add_string(&b, "value", value));
CHECK(blobmsg_add_u32(&b, "ttl", ttl));
ret = ubus_notify(ubus, &ubus_object, "connmark-allowlist.resolved", b.head, /* timeout: */ 1000);
if (ret)
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
/* Set timeout to allow UBus subscriber to configure firewall rules before returning. */
CHECK(ubus_notify(ubus, &ubus_object, "connmark-allowlist.resolved", b.head, /* timeout: */ 1000));
}
#endif
#undef CHECK
#endif /* HAVE_UBUS */
+41 -19
View File
@@ -115,7 +115,8 @@ u64 rand64(void)
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)
{
/* remove trailing .
@@ -123,7 +124,9 @@ static int check_name(char *in)
size_t dotgap = 0, l = strlen(in);
char c;
int nowhite = 0;
int idn_encode = 0;
int hasuscore = 0;
int hasucase = 0;
if (l == 0 || l > MAXDNAME) return 0;
@@ -136,28 +139,49 @@ static int check_name(char *in)
for (; (c = *in); in++)
{
if (c == '.')
dotgap = 0;
dotgap = 0;
else if (++dotgap > MAXLABEL)
return 0;
return 0;
else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))
/* iscntrl only gives expected results for ascii */
return 0;
#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2)
/* iscntrl only gives expected results for ascii */
return 0;
else if (!isascii((unsigned char)c))
return 0;
#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2)
return 0;
#else
idn_encode = 1;
#endif
else if (c != ' ')
{
nowhite = 1;
if (c == '_')
hasuscore = 1;
}
{
nowhite = 1;
#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
if (c == '_')
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)
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
@@ -204,12 +228,8 @@ char *canonicalise(char *in, int *nomem)
if (!(rc = check_name(in)))
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 (rc == 2)
{
# ifdef HAVE_LIBIDN2
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
@@ -234,12 +254,14 @@ char *canonicalise(char *in, int *nomem)
return ret;
}
#else
(void)rc;
#endif
if ((ret = whine_malloc(strlen(in)+1)))
strcpy(ret, in);
else if (nomem)
*nomem = 1;
*nomem = 1;
return ret;
}