mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
39
Commits
v2.86test5
...
v2.86
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cac9ca38f6 | ||
|
|
51d56df7a3 | ||
|
|
860a9a57d6 | ||
|
|
c83e33d608 | ||
|
|
7b80c75d9d | ||
|
|
79337f99ae | ||
|
|
a42ee397f3 | ||
|
|
e58f8bb8c1 | ||
|
|
58cf958e41 | ||
|
|
06d01f7ae4 | ||
|
|
1a33eec0ba | ||
|
|
82de7a1e96 | ||
|
|
8e9bde57c5 | ||
|
|
1bb70e08be | ||
|
|
9afcb7ae61 | ||
|
|
545c4955e6 | ||
|
|
2f2d59b35c | ||
|
|
a1729deed3 | ||
|
|
fc64b97cd5 | ||
|
|
daddc8cb80 | ||
|
|
527c3c7d0d | ||
|
|
fcb4dcaf7c | ||
|
|
3ca4995d34 | ||
|
|
d387f8f06c | ||
|
|
ea43234c86 | ||
|
|
867e56a45e | ||
|
|
a163c63787 | ||
|
|
8389b943d3 | ||
|
|
f2266d9678 | ||
|
|
56bd806978 | ||
|
|
ac7eeea44d | ||
|
|
b741059549 | ||
|
|
cbd984287f | ||
|
|
32e15c3f45 | ||
|
|
f0dc324e35 | ||
|
|
f83c6cf51a | ||
|
|
c068b3ae2f | ||
|
|
adf9dec1e6 | ||
|
|
767d9cbd96 |
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
version 2.86
|
version 2.86
|
||||||
Handle DHCPREBIND requests in the DHCPv6 server code.
|
Handle DHCPREBIND requests in the DHCPv6 server code.
|
||||||
Thanks to Aichun Li for spotting this ommision, and the initial
|
Thanks to Aichun Li for spotting this omission, and the initial
|
||||||
patch.
|
patch.
|
||||||
|
|
||||||
Fix bug which caused dnsmasq to lose track of processes forked
|
Fix bug which caused dnsmasq to lose track of processes forked
|
||||||
@@ -33,7 +33,7 @@ version 2.86
|
|||||||
address=/example.com/1.2.3.4
|
address=/example.com/1.2.3.4
|
||||||
address=/example.com/5.6.7.8
|
address=/example.com/5.6.7.8
|
||||||
It also handles multiple upstream servers for a domain better; using
|
It also handles multiple upstream servers for a domain better; using
|
||||||
the same try/retry alogrithms as non domain-specific servers. This
|
the same try/retry algorithms as non domain-specific servers. This
|
||||||
also applies to DNSSEC-generated queries.
|
also applies to DNSSEC-generated queries.
|
||||||
Finally, some of the oldest and gnarliest code in dnsmasq has had
|
Finally, some of the oldest and gnarliest code in dnsmasq has had
|
||||||
a significant clean-up. It's far from perfect, but it _is_ better.
|
a significant clean-up. It's far from perfect, but it _is_ better.
|
||||||
@@ -76,6 +76,22 @@ version 2.86
|
|||||||
Disallowed queries are not forwarded; they are rejected
|
Disallowed queries are not forwarded; they are rejected
|
||||||
with a REFUSED error code.
|
with a REFUSED error code.
|
||||||
|
|
||||||
|
Allow smaller than 64 prefix lengths in synth-domain, with caveats.
|
||||||
|
--synth-domain=1234:4567::/56,example.com is now valid.
|
||||||
|
|
||||||
|
Make domains generated by --synth-domain appear in replies
|
||||||
|
when in authoritative mode.
|
||||||
|
|
||||||
|
Ensure CAP_NET_ADMIN capability is available when
|
||||||
|
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
|
version 2.85
|
||||||
Fix problem with DNS retries in 2.83/2.84.
|
Fix problem with DNS retries in 2.83/2.84.
|
||||||
@@ -147,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
|
||||||
|
|||||||
@@ -153,7 +153,11 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lease.s_addr = inet_addr(argv[1]);
|
if (inet_pton(AF_INET, argv[1], &lease) < 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "invalid address: %s\n", argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
memset(&packet, 0, sizeof(packet));
|
memset(&packet, 0, sizeof(packet));
|
||||||
|
|
||||||
@@ -176,8 +180,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
*(p++) = OPTION_END;
|
*(p++) = OPTION_END;
|
||||||
|
|
||||||
dest.sin_family = AF_INET;
|
dest.sin_family = AF_INET;
|
||||||
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
|
(void)inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr);
|
||||||
dest.sin_port = ntohs(DHCP_SERVER_PORT);
|
dest.sin_port = ntohs(DHCP_SERVER_PORT);
|
||||||
|
|
||||||
if (sendto(fd, &packet, sizeof(packet), 0,
|
if (sendto(fd, &packet, sizeof(packet), 0,
|
||||||
|
|||||||
@@ -288,13 +288,12 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inet_addr(argv[2]) == INADDR_NONE)
|
if (inet_pton(AF_INET, argv[2], &lease.s_addr) < 1)
|
||||||
{
|
{
|
||||||
perror("invalid ip address");
|
perror("invalid ip address");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lease.s_addr = inet_addr(argv[2]);
|
|
||||||
server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr);
|
server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr);
|
||||||
|
|
||||||
memset(&packet, 0, sizeof(packet));
|
memset(&packet, 0, sizeof(packet));
|
||||||
|
|||||||
+24
-10
@@ -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
|
||||||
@@ -705,7 +706,8 @@ configured a zero is added in front of the label. ::1 becomes 0--1.
|
|||||||
V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
|
V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
|
||||||
|
|
||||||
The address range can be of the form
|
The address range can be of the form
|
||||||
<ip address>,<ip address> or <ip address>/<netmask> in both forms of the option.
|
<start address>,<end address> or <ip address>/<prefix-length> in both forms of the option. For IPv6 the start and end addresses
|
||||||
|
must fall in the same /64 network, or prefix-length must be greater than or equal to 64 except that shorter prefix lengths than 64 are allowed only if non-sequential names are in use.
|
||||||
.TP
|
.TP
|
||||||
.B --dumpfile=<path/to/file>
|
.B --dumpfile=<path/to/file>
|
||||||
Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end.
|
Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end.
|
||||||
@@ -904,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>]
|
||||||
|
|
||||||
@@ -1164,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:
|
||||||
@@ -1172,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
|
||||||
@@ -1187,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.
|
||||||
@@ -1432,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
|
||||||
@@ -1612,10 +1621,11 @@ tried. This flag disables this check. Use with caution.
|
|||||||
Extra logging for DHCP: log all the options sent to DHCP clients and
|
Extra logging for DHCP: log all the options sent to DHCP clients and
|
||||||
the tags used to determine them.
|
the tags used to determine them.
|
||||||
.TP
|
.TP
|
||||||
.B --quiet-dhcp, --quiet-dhcp6, --quiet-ra
|
.B --quiet-dhcp, --quiet-dhcp6, --quiet-ra, --quiet-tftp
|
||||||
Suppress logging of the routine operation of these protocols. Errors and
|
Suppress logging of the routine operation of these protocols. Errors and
|
||||||
problems will still be logged. \fB--quiet-dhcp\fP and quiet-dhcp6 are
|
problems will still be logged. \fB--quiet-tftp\fP does not consider file not
|
||||||
over-ridden by \fB--log-dhcp\fP.
|
found to be an error. \fB--quiet-dhcp\fP and quiet-dhcp6 are over-ridden by
|
||||||
|
\fB--log-dhcp\fP.
|
||||||
.TP
|
.TP
|
||||||
.B \-l, --dhcp-leasefile=<path>
|
.B \-l, --dhcp-leasefile=<path>
|
||||||
Use the specified file to store DHCP lease information.
|
Use the specified file to store DHCP lease information.
|
||||||
@@ -2417,6 +2427,10 @@ following data is used to populate the authoritative zone.
|
|||||||
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record, --caa-record,
|
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record, --caa-record,
|
||||||
as long as the record names are in the authoritative domain.
|
as long as the record names are in the authoritative domain.
|
||||||
.PP
|
.PP
|
||||||
|
.B --synth-domain
|
||||||
|
as long as the domain is in the authoritative zone and, for
|
||||||
|
reverse (PTR) queries, the address is in the relevant subnet.
|
||||||
|
.PP
|
||||||
.B --cname
|
.B --cname
|
||||||
as long as the record name is in the authoritative domain. If the
|
as long as the record name is in the authoritative domain. If the
|
||||||
target of the CNAME is unqualified, then it is qualified with the
|
target of the CNAME is unqualified, then it is qualified with the
|
||||||
|
|||||||
+731
-579
File diff suppressed because it is too large.
Load diff
+38
-1
@@ -105,7 +105,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
int nameoffset, axfroffset = 0;
|
int nameoffset, axfroffset = 0;
|
||||||
int q, anscount = 0, authcount = 0;
|
int q, anscount = 0, authcount = 0;
|
||||||
struct crec *crecp;
|
struct crec *crecp;
|
||||||
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
|
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0, out_of_zone = 0;
|
||||||
struct auth_zone *zone = NULL;
|
struct auth_zone *zone = NULL;
|
||||||
struct addrlist *subnet = NULL;
|
struct addrlist *subnet = NULL;
|
||||||
char *cut;
|
char *cut;
|
||||||
@@ -146,6 +146,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (qclass != C_IN)
|
if (qclass != C_IN)
|
||||||
{
|
{
|
||||||
auth = 0;
|
auth = 0;
|
||||||
|
out_of_zone = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,6 +160,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (!zone)
|
if (!zone)
|
||||||
{
|
{
|
||||||
|
out_of_zone = 1;
|
||||||
auth = 0;
|
auth = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -253,6 +255,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
||||||
|
|
||||||
|
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);
|
||||||
|
found = 1;
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
else
|
else
|
||||||
@@ -273,6 +286,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (!zone)
|
if (!zone)
|
||||||
{
|
{
|
||||||
|
out_of_zone = 1;
|
||||||
auth = 0;
|
auth = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -400,6 +414,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found && is_name_synthetic(flag, name, &addr) )
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
nxdomain = 0;
|
||||||
|
|
||||||
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cut)
|
if (!cut)
|
||||||
{
|
{
|
||||||
@@ -855,10 +880,22 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
SET_RCODE(header, NXDOMAIN);
|
SET_RCODE(header, NXDOMAIN);
|
||||||
else
|
else
|
||||||
SET_RCODE(header, NOERROR); /* no error */
|
SET_RCODE(header, NOERROR); /* no error */
|
||||||
|
|
||||||
header->ancount = htons(anscount);
|
header->ancount = htons(anscount);
|
||||||
header->nscount = htons(authcount);
|
header->nscount = htons(authcount);
|
||||||
header->arcount = htons(0);
|
header->arcount = htons(0);
|
||||||
|
|
||||||
|
if (!local_query && out_of_zone)
|
||||||
|
{
|
||||||
|
SET_RCODE(header, REFUSED);
|
||||||
|
header->ancount = htons(0);
|
||||||
|
header->nscount = htons(0);
|
||||||
|
addr.log.rcode = REFUSED;
|
||||||
|
addr.log.ede = EDE_NOT_AUTH;
|
||||||
|
log_query(F_UPSTREAM | F_RCODE, "error", &addr, NULL);
|
||||||
|
return resize_packet(header, ansp - (unsigned char *)header, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Advertise our packet size limit in our reply */
|
/* Advertise our packet size limit in our reply */
|
||||||
if (have_pseudoheader)
|
if (have_pseudoheader)
|
||||||
return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||||
|
|||||||
+14
-10
@@ -488,8 +488,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)
|
||||||
@@ -1855,7 +1853,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1897,17 +1895,24 @@ 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)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
|
#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 +1934,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
|
||||||
|
dest = arg;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
dest = arg;
|
|
||||||
|
|
||||||
if (flags & F_REVERSE)
|
if (flags & F_REVERSE)
|
||||||
{
|
{
|
||||||
@@ -1974,7 +1978,7 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
|
|||||||
source = "reply";
|
source = "reply";
|
||||||
else if (flags & F_SECSTAT)
|
else if (flags & F_SECSTAT)
|
||||||
{
|
{
|
||||||
if (addr && addr->log.ede != EDE_UNSET)
|
if (addr && addr->log.ede != EDE_UNSET && option_bool(OPT_EXTRALOG))
|
||||||
{
|
{
|
||||||
extra = daemon->addrbuff;
|
extra = daemon->addrbuff;
|
||||||
sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
|
sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
|
||||||
@@ -2023,5 +2027,5 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
|
my_syslog(LOG_INFO, "%s %s %s %s%s", source, name, verb, dest, extra);
|
||||||
}
|
}
|
||||||
+36
-1
@@ -79,13 +79,46 @@ ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
|||||||
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
|
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* like match_netid() except that the check can have a trailing * for wildcard */
|
||||||
|
/* started as a direct copy of match_netid() */
|
||||||
|
int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool)
|
||||||
|
{
|
||||||
|
struct dhcp_netid *tmp1;
|
||||||
|
|
||||||
|
for (; check; check = check->next)
|
||||||
|
{
|
||||||
|
const int check_len = strlen(check->net);
|
||||||
|
const int is_wc = (check->net[check_len - 1] == '*');
|
||||||
|
|
||||||
|
/* '#' for not is for backwards compat. */
|
||||||
|
if (check->net[0] != '!' && check->net[0] != '#')
|
||||||
|
{
|
||||||
|
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
|
||||||
|
if (is_wc ? (strncmp(check->net, tmp1->net, check_len-1) == 0) :
|
||||||
|
(strcmp(check->net, tmp1->net) == 0))
|
||||||
|
break;
|
||||||
|
if (!tmp1)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
|
||||||
|
if (is_wc ? (strncmp((check->net)+1, tmp1->net, check_len-2) == 0) :
|
||||||
|
(strcmp((check->net)+1, tmp1->net) == 0))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
|
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
|
||||||
{
|
{
|
||||||
struct tag_if *exprs;
|
struct tag_if *exprs;
|
||||||
struct dhcp_netid_list *list;
|
struct dhcp_netid_list *list;
|
||||||
|
|
||||||
|
/* this now uses match_netid_wild() above so that tag_if can
|
||||||
|
* be used to set a 'group of interfaces' tag.
|
||||||
|
*/
|
||||||
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
|
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
|
||||||
if (match_netid(exprs->tag, tags, 1))
|
if (match_netid_wild(exprs->tag, tags))
|
||||||
for (list = exprs->set; list; list = list->next)
|
for (list = exprs->set; list; list = list->next)
|
||||||
{
|
{
|
||||||
list->list->next = tags;
|
list->list->next = tags;
|
||||||
@@ -620,6 +653,8 @@ static const struct opttab_t {
|
|||||||
{ "client-arch", 93, 2 | OT_DEC },
|
{ "client-arch", 93, 2 | OT_DEC },
|
||||||
{ "client-interface-id", 94, 0 },
|
{ "client-interface-id", 94, 0 },
|
||||||
{ "client-machine-id", 97, 0 },
|
{ "client-machine-id", 97, 0 },
|
||||||
|
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||||
|
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||||
{ "subnet-select", 118, OT_INTERNAL },
|
{ "subnet-select", 118, OT_INTERNAL },
|
||||||
{ "domain-search", 119, OT_RFC1035_NAME },
|
{ "domain-search", 119, OT_RFC1035_NAME },
|
||||||
{ "sip-server", 120, 0 },
|
{ "sip-server", 120, 0 },
|
||||||
|
|||||||
+12
-7
@@ -468,8 +468,11 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
|
|
||||||
/* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
|
/* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
|
{
|
||||||
inet_ntoa(dest.sin_addr), strerror(errno));
|
inet_ntop(AF_INET, &dest.sin_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
|
||||||
|
daemon->addrbuff, strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check against secondary interface addresses */
|
/* check against secondary interface addresses */
|
||||||
@@ -521,10 +524,11 @@ static void guess_range_netmask(struct in_addr addr, struct in_addr netmask)
|
|||||||
!(is_same_net(addr, context->start, netmask) &&
|
!(is_same_net(addr, context->start, netmask) &&
|
||||||
is_same_net(addr, context->end, netmask)))
|
is_same_net(addr, context->end, netmask)))
|
||||||
{
|
{
|
||||||
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
|
inet_ntop(AF_INET, &context->start, daemon->dhcp_buff, DHCP_BUFF_SZ);
|
||||||
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
|
inet_ntop(AF_INET, &context->end, daemon->dhcp_buff2, DHCP_BUFF_SZ);
|
||||||
|
inet_ntop(AF_INET, &netmask, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
|
||||||
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
|
daemon->dhcp_buff, daemon->dhcp_buff2, daemon->addrbuff);
|
||||||
}
|
}
|
||||||
context->netmask = netmask;
|
context->netmask = netmask;
|
||||||
}
|
}
|
||||||
@@ -922,7 +926,7 @@ void dhcp_read_ethers(void)
|
|||||||
|
|
||||||
if (!*cp)
|
if (!*cp)
|
||||||
{
|
{
|
||||||
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1)
|
if (inet_pton(AF_INET, ip, &addr.s_addr) < 1)
|
||||||
{
|
{
|
||||||
my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
|
my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
|
||||||
continue;
|
continue;
|
||||||
@@ -1097,7 +1101,8 @@ static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess,
|
|||||||
if (option_bool(OPT_LOG_OPTS))
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, inet_ntoa(relay->server.addr4));
|
inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ);
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save this for replies */
|
/* Save this for replies */
|
||||||
|
|||||||
+7
-3
@@ -109,7 +109,6 @@ int main (int argc, char **argv)
|
|||||||
daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
|
daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
|
||||||
daemon->packet = safe_malloc(daemon->packet_buff_sz);
|
daemon->packet = safe_malloc(daemon->packet_buff_sz);
|
||||||
|
|
||||||
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
|
||||||
if (option_bool(OPT_EXTRALOG))
|
if (option_bool(OPT_EXTRALOG))
|
||||||
daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
|
daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
|
||||||
|
|
||||||
@@ -212,8 +211,13 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
|
if (option_bool(OPT_CONNTRACK))
|
||||||
die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
|
{
|
||||||
|
if (daemon->query_port != 0 || daemon->osport)
|
||||||
|
die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
|
||||||
|
|
||||||
|
need_cap_net_admin = 1;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (option_bool(OPT_CONNTRACK))
|
if (option_bool(OPT_CONNTRACK))
|
||||||
die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
|
die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
|
||||||
|
|||||||
+5
-3
@@ -107,6 +107,7 @@ typedef unsigned long long u64;
|
|||||||
#endif
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -273,7 +274,8 @@ struct event_desc {
|
|||||||
#define OPT_UMBRELLA 63
|
#define OPT_UMBRELLA 63
|
||||||
#define OPT_UMBRELLA_DEVID 64
|
#define OPT_UMBRELLA_DEVID 64
|
||||||
#define OPT_CMARK_ALST_EN 65
|
#define OPT_CMARK_ALST_EN 65
|
||||||
#define OPT_LAST 66
|
#define OPT_QUIET_TFTP 66
|
||||||
|
#define OPT_LAST 67
|
||||||
|
|
||||||
#define OPTION_BITS (sizeof(unsigned int)*8)
|
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||||
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
||||||
@@ -959,10 +961,10 @@ struct dhcp_bridge {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cond_domain {
|
struct cond_domain {
|
||||||
char *domain, *prefix;
|
char *domain, *prefix; /* prefix is text-prefix on domain name */
|
||||||
struct in_addr start, end;
|
struct in_addr start, end;
|
||||||
struct in6_addr start6, end6;
|
struct in6_addr start6, end6;
|
||||||
int is6, indexed;
|
int is6, indexed, prefixlen;
|
||||||
struct cond_domain *next;
|
struct cond_domain *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -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)))
|
||||||
|
|||||||
+36
-32
@@ -18,8 +18,9 @@
|
|||||||
|
|
||||||
|
|
||||||
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
|
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
|
||||||
|
static int match_domain(struct in_addr addr, struct cond_domain *c);
|
||||||
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
|
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||||
|
static int match_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||||
|
|
||||||
int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||||
{
|
{
|
||||||
@@ -135,28 +136,9 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
||||||
{
|
found = (prot == AF_INET) ? match_domain(addr->addr4, c) : match_domain6(&addr->addr6, c);
|
||||||
if (prot == AF_INET)
|
|
||||||
{
|
|
||||||
if (!c->is6 &&
|
|
||||||
ntohl(addr->addr4.s_addr) >= ntohl(c->start.s_addr) &&
|
|
||||||
ntohl(addr->addr4.s_addr) <= ntohl(c->end.s_addr))
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u64 addrpart = addr6part(&addr->addr6);
|
|
||||||
|
|
||||||
if (c->is6 &&
|
|
||||||
is_same_net6(&addr->addr6, &c->start6, 64) &&
|
|
||||||
addrpart >= addr6part(&c->start6) &&
|
|
||||||
addrpart <= addr6part(&c->end6))
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore name */
|
/* restore name */
|
||||||
for (p = tail; *p; p++)
|
for (p = tail; *p; p++)
|
||||||
if (*p == '.' || *p == ':')
|
if (*p == '.' || *p == ':')
|
||||||
@@ -246,14 +228,22 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int match_domain(struct in_addr addr, struct cond_domain *c)
|
||||||
|
{
|
||||||
|
if (!c->is6 &&
|
||||||
|
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||||
|
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
|
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
|
||||||
{
|
{
|
||||||
for (; c; c = c->next)
|
for (; c; c = c->next)
|
||||||
if (!c->is6 &&
|
if (match_domain(addr, c))
|
||||||
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
|
||||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,16 +257,30 @@ char *get_domain(struct in_addr addr)
|
|||||||
return daemon->domain_suffix;
|
return daemon->domain_suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||||
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
|
|
||||||
{
|
{
|
||||||
u64 addrpart = addr6part(addr);
|
u64 addrpart = addr6part(addr);
|
||||||
|
|
||||||
|
if (c->is6)
|
||||||
|
{
|
||||||
|
if (c->prefixlen >= 64)
|
||||||
|
{
|
||||||
|
if (is_same_net6(addr, &c->start6, 64) &&
|
||||||
|
addrpart >= addr6part(&c->start6) &&
|
||||||
|
addrpart <= addr6part(&c->end6))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (is_same_net6(addr, &c->start6, c->prefixlen))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||||
|
{
|
||||||
for (; c; c = c->next)
|
for (; c; c = c->next)
|
||||||
if (c->is6 &&
|
if (match_domain6(addr, c))
|
||||||
is_same_net6(addr, &c->start6, 64) &&
|
|
||||||
addrpart >= addr6part(&c->start6) &&
|
|
||||||
addrpart <= addr6part(&c->end6))
|
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
+31
-26
@@ -255,29 +255,25 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
/* new query */
|
/* new query */
|
||||||
if (!forward)
|
if (!forward)
|
||||||
{
|
{
|
||||||
/* new query */
|
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
|
||||||
|
flags = is_local_answer(now, first, daemon->namebuff);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no available server. */
|
||||||
|
ede = EDE_NOT_READY;
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* don't forward A or AAAA queries for simple names, except the empty name */
|
/* don't forward A or AAAA queries for simple names, except the empty name */
|
||||||
if (option_bool(OPT_NODOTS_LOCAL) &&
|
if (!flags &&
|
||||||
|
option_bool(OPT_NODOTS_LOCAL) &&
|
||||||
(gotname & (F_IPV4 | F_IPV6)) &&
|
(gotname & (F_IPV4 | F_IPV6)) &&
|
||||||
!strchr(daemon->namebuff, '.') &&
|
!strchr(daemon->namebuff, '.') &&
|
||||||
strlen(daemon->namebuff) != 0)
|
strlen(daemon->namebuff) != 0)
|
||||||
{
|
flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN;
|
||||||
flags = F_NOERR;
|
|
||||||
goto reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = 0;
|
|
||||||
|
|
||||||
/* no available server. */
|
|
||||||
if (!lookup_domain(daemon->namebuff, gotname, &first, &last))
|
|
||||||
{
|
|
||||||
ede = EDE_NOT_READY;
|
|
||||||
goto reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configured answer. */
|
/* Configured answer. */
|
||||||
if ((flags = is_local_answer(now, first, daemon->namebuff)))
|
if (flags || ede == EDE_NOT_READY)
|
||||||
goto reply;
|
goto reply;
|
||||||
|
|
||||||
master = daemon->serverarray[first];
|
master = daemon->serverarray[first];
|
||||||
@@ -537,7 +533,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
{
|
{
|
||||||
u16 swap = htons((u16)ede);
|
u16 swap = htons((u16)ede);
|
||||||
|
|
||||||
if (ede != -EDE_UNSET)
|
if (ede != EDE_UNSET)
|
||||||
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
||||||
else
|
else
|
||||||
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||||
@@ -2037,16 +2033,25 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
{
|
{
|
||||||
struct server *master;
|
struct server *master;
|
||||||
int start;
|
int start;
|
||||||
|
|
||||||
|
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
|
||||||
|
flags = is_local_answer(now, first, daemon->namebuff);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No configured servers */
|
||||||
|
ede = EDE_NOT_READY;
|
||||||
|
flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* don't forward A or AAAA queries for simple names, except the empty name */
|
/* don't forward A or AAAA queries for simple names, except the empty name */
|
||||||
if (option_bool(OPT_NODOTS_LOCAL) &&
|
if (!flags &&
|
||||||
|
option_bool(OPT_NODOTS_LOCAL) &&
|
||||||
(gotname & (F_IPV4 | F_IPV6)) &&
|
(gotname & (F_IPV4 | F_IPV6)) &&
|
||||||
!strchr(daemon->namebuff, '.') &&
|
!strchr(daemon->namebuff, '.') &&
|
||||||
strlen(daemon->namebuff) != 0)
|
strlen(daemon->namebuff) != 0)
|
||||||
flags = F_NOERR;
|
flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN;
|
||||||
else if (!lookup_domain(daemon->namebuff, gotname, &first, &last))
|
|
||||||
ede = EDE_NOT_READY; /* No configured servers */
|
if (!flags && ede != EDE_NOT_READY)
|
||||||
else if (!(flags = is_local_answer(now, first, daemon->namebuff)))
|
|
||||||
{
|
{
|
||||||
master = daemon->serverarray[first];
|
master = daemon->serverarray[first];
|
||||||
|
|
||||||
@@ -2093,10 +2098,10 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
|
int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname,
|
||||||
serv, have_mark, mark, &keycount);
|
serv, have_mark, mark, &keycount);
|
||||||
char *result, *domain = "result";
|
char *result, *domain = "result";
|
||||||
|
|
||||||
union all_addr a;
|
union all_addr a;
|
||||||
a.log.ede = ede = errflags_to_ede(status);
|
a.log.ede = ede = errflags_to_ede(status);
|
||||||
|
|
||||||
if (STAT_ISEQUAL(status, STAT_ABANDONED))
|
if (STAT_ISEQUAL(status, STAT_ABANDONED))
|
||||||
{
|
{
|
||||||
result = "ABANDONED";
|
result = "ABANDONED";
|
||||||
@@ -2137,7 +2142,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case of local answer or no connections made. */
|
/* In case of local answer or no connections made. */
|
||||||
if (m == 0)
|
if (m == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
+9
-3
@@ -432,7 +432,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
buf = grab_extradata_lua(buf, end, "relay_address");
|
buf = grab_extradata_lua(buf, end, "relay_address");
|
||||||
else if (data.giaddr.s_addr != 0)
|
else if (data.giaddr.s_addr != 0)
|
||||||
{
|
{
|
||||||
lua_pushstring(lua, inet_ntoa(data.giaddr));
|
inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
lua_pushstring(lua, daemon->addrbuff);
|
||||||
lua_setfield(lua, -2, "relay_address");
|
lua_setfield(lua, -2, "relay_address");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,8 +611,13 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
|
|
||||||
if (is6)
|
if (is6)
|
||||||
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
|
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
|
||||||
else
|
else
|
||||||
my_setenv("DNSMASQ_RELAY_ADDRESS", data.giaddr.s_addr != 0 ? inet_ntoa(data.giaddr) : NULL, &err);
|
{
|
||||||
|
const char *giaddr = NULL;
|
||||||
|
if (data.giaddr.s_addr != 0)
|
||||||
|
giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
my_setenv("DNSMASQ_RELAY_ADDRESS", giaddr, &err);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; buf; i++)
|
for (i = 0; buf; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -1688,7 +1688,7 @@ int reload_servers(char *fname)
|
|||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
memset(&source_addr, 0, sizeof(source_addr));
|
memset(&source_addr, 0, sizeof(source_addr));
|
||||||
|
|
||||||
if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
if (inet_pton(AF_INET, token, &addr.in.sin_addr) > 0)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
|
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
|
||||||
|
|||||||
+87
-39
@@ -173,6 +173,7 @@ struct myoption {
|
|||||||
#define LOPT_UMBRELLA 364
|
#define LOPT_UMBRELLA 364
|
||||||
#define LOPT_CMARK_ALST_EN 365
|
#define LOPT_CMARK_ALST_EN 365
|
||||||
#define LOPT_CMARK_ALST 366
|
#define LOPT_CMARK_ALST 366
|
||||||
|
#define LOPT_QUIET_TFTP 367
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
static const struct option opts[] =
|
static const struct option opts[] =
|
||||||
@@ -351,6 +352,7 @@ static const struct myoption opts[] =
|
|||||||
{ "dynamic-host", 1, 0, LOPT_DYNHOST },
|
{ "dynamic-host", 1, 0, LOPT_DYNHOST },
|
||||||
{ "log-debug", 0, 0, LOPT_LOG_DEBUG },
|
{ "log-debug", 0, 0, LOPT_LOG_DEBUG },
|
||||||
{ "umbrella", 2, 0, LOPT_UMBRELLA },
|
{ "umbrella", 2, 0, LOPT_UMBRELLA },
|
||||||
|
{ "quiet-tftp", 0, 0, LOPT_QUIET_TFTP },
|
||||||
{ NULL, 0, 0, 0 }
|
{ NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -536,6 +538,7 @@ static struct {
|
|||||||
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
|
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
|
||||||
{ LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL },
|
{ LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL },
|
||||||
{ LOPT_UMBRELLA, ARG_ONE, "[=<optspec>]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL },
|
{ LOPT_UMBRELLA, ARG_ONE, "[=<optspec>]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL },
|
||||||
|
{ LOPT_QUIET_TFTP, OPT_QUIET_TFTP, NULL, gettext_noop("Do not log routine TFTP."), NULL },
|
||||||
{ 0, 0, NULL, NULL, NULL }
|
{ 0, 0, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -651,7 +654,7 @@ static char *canonicalise_opt(char *s)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strlen(s) == 0)
|
if (strlen(s) == 0)
|
||||||
return "";
|
return opt_string_alloc("");
|
||||||
|
|
||||||
unhide_metas(s);
|
unhide_metas(s);
|
||||||
if (!(ret = canonicalise(s, &nomem)) && nomem)
|
if (!(ret = canonicalise(s, &nomem)) && nomem)
|
||||||
@@ -965,7 +968,7 @@ static int domain_rev6(char *domain, struct in6_addr *addr, int msize)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (msize%4)
|
if (msize > 128 || msize%4)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*domain = 0;
|
*domain = 0;
|
||||||
@@ -1185,11 +1188,15 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|||||||
{
|
{
|
||||||
new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
|
new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
|
||||||
new->flags |= DHOPT_VENDOR;
|
new->flags |= DHOPT_VENDOR;
|
||||||
|
if ((new->flags & DHOPT_ENCAPSULATE) || flags == DHOPT_MATCH)
|
||||||
|
goto_err(_("inappropriate vendor:"));
|
||||||
}
|
}
|
||||||
else if (strstr(arg, "encap:") == arg)
|
else if (strstr(arg, "encap:") == arg)
|
||||||
{
|
{
|
||||||
new->u.encap = atoi(arg+6);
|
new->u.encap = atoi(arg+6);
|
||||||
new->flags |= DHOPT_ENCAPSULATE;
|
new->flags |= DHOPT_ENCAPSULATE;
|
||||||
|
if ((new->flags & DHOPT_VENDOR) || flags == DHOPT_MATCH)
|
||||||
|
goto_err(_("inappropriate encap:"));
|
||||||
}
|
}
|
||||||
else if (strstr(arg, "vi-encap:") == arg)
|
else if (strstr(arg, "vi-encap:") == arg)
|
||||||
{
|
{
|
||||||
@@ -2224,7 +2231,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
arg = comma;
|
arg = comma;
|
||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
daemon->hostmaster = opt_string_alloc(arg);
|
daemon->hostmaster = opt_string_alloc(arg);
|
||||||
for (cp = daemon->hostmaster; *cp; cp++)
|
for (cp = daemon->hostmaster; cp && *cp; cp++)
|
||||||
if (*cp == '@')
|
if (*cp == '@')
|
||||||
*cp = '.';
|
*cp = '.';
|
||||||
|
|
||||||
@@ -2254,10 +2261,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
char *d, *d_raw = arg;
|
char *d, *d_raw = arg;
|
||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
if (!(d = canonicalise_opt(arg)))
|
if (!(d = canonicalise_opt(d_raw)))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
free(d); /* allocate this again below. */
|
||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
|
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
|
||||||
@@ -2265,6 +2273,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
new->prefix = NULL;
|
new->prefix = NULL;
|
||||||
new->indexed = 0;
|
new->indexed = 0;
|
||||||
|
new->prefixlen = 0;
|
||||||
|
|
||||||
unhide_metas(comma);
|
unhide_metas(comma);
|
||||||
if ((netpart = split_chr(comma, '/')))
|
if ((netpart = split_chr(comma, '/')))
|
||||||
@@ -2276,7 +2285,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
ret_err_free(gen_err, new);
|
ret_err_free(gen_err, new);
|
||||||
else if (inet_pton(AF_INET, comma, &new->start))
|
else if (inet_pton(AF_INET, comma, &new->start))
|
||||||
{
|
{
|
||||||
int mask = (1 << (32 - msize)) - 1;
|
int mask;
|
||||||
|
|
||||||
|
if (msize > 32)
|
||||||
|
ret_err_free(_("bad prefix length"), new);
|
||||||
|
|
||||||
|
mask = (1 << (32 - msize)) - 1;
|
||||||
new->is6 = 0;
|
new->is6 = 0;
|
||||||
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
|
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
|
||||||
new->end.s_addr = new->start.s_addr | htonl(mask);
|
new->end.s_addr = new->start.s_addr | htonl(mask);
|
||||||
@@ -2307,21 +2321,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
else if (inet_pton(AF_INET6, comma, &new->start6))
|
else if (inet_pton(AF_INET6, comma, &new->start6))
|
||||||
{
|
{
|
||||||
u64 mask = (1LLU << (128 - msize)) - 1LLU;
|
u64 mask, addrpart = addr6part(&new->start6);
|
||||||
u64 addrpart = addr6part(&new->start6);
|
|
||||||
|
if (msize > 128)
|
||||||
|
ret_err_free(_("bad prefix length"), new);
|
||||||
|
|
||||||
|
mask = (1LLU << (128 - msize)) - 1LLU;
|
||||||
|
|
||||||
new->is6 = 1;
|
new->is6 = 1;
|
||||||
|
new->prefixlen = msize;
|
||||||
|
|
||||||
/* prefix==64 overflows the mask calculation above */
|
/* prefix==64 overflows the mask calculation above */
|
||||||
if (msize == 64)
|
if (msize <= 64)
|
||||||
mask = (u64)-1LL;
|
mask = (u64)-1LL;
|
||||||
|
|
||||||
new->end6 = new->start6;
|
new->end6 = new->start6;
|
||||||
setaddr6part(&new->start6, addrpart & ~mask);
|
setaddr6part(&new->start6, addrpart & ~mask);
|
||||||
setaddr6part(&new->end6, addrpart | mask);
|
setaddr6part(&new->end6, addrpart | mask);
|
||||||
|
|
||||||
if (msize < 64)
|
if (arg)
|
||||||
ret_err_free(gen_err, new);
|
|
||||||
else if (arg)
|
|
||||||
{
|
{
|
||||||
if (option != 's')
|
if (option != 's')
|
||||||
{
|
{
|
||||||
@@ -2381,7 +2399,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new->domain = d;
|
new->domain = canonicalise_opt(d_raw);
|
||||||
if (option == 's')
|
if (option == 's')
|
||||||
{
|
{
|
||||||
new->next = daemon->cond_domain;
|
new->next = daemon->cond_domain;
|
||||||
@@ -2390,19 +2408,21 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *star;
|
char *star;
|
||||||
new->next = daemon->synth_domains;
|
|
||||||
daemon->synth_domains = new;
|
|
||||||
if (new->prefix &&
|
if (new->prefix &&
|
||||||
(star = strrchr(new->prefix, '*'))
|
(star = strrchr(new->prefix, '*'))
|
||||||
&& *(star+1) == 0)
|
&& *(star+1) == 0)
|
||||||
{
|
{
|
||||||
*star = 0;
|
*star = 0;
|
||||||
new->indexed = 1;
|
new->indexed = 1;
|
||||||
|
if (new->is6 && new->prefixlen < 64)
|
||||||
|
ret_err_free(_("prefix length too small"), new);
|
||||||
}
|
}
|
||||||
|
new->next = daemon->synth_domains;
|
||||||
|
daemon->synth_domains = new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (option == 's')
|
else if (option == 's')
|
||||||
daemon->domain_suffix = d;
|
daemon->domain_suffix = canonicalise_opt(d_raw);
|
||||||
else
|
else
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
}
|
}
|
||||||
@@ -2680,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')
|
||||||
@@ -2692,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);
|
||||||
|
|
||||||
@@ -3592,7 +3613,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
for (configs = daemon->dhcp_conf; configs; configs = configs->next)
|
for (configs = daemon->dhcp_conf; configs; configs = configs->next)
|
||||||
if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
|
if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
|
||||||
{
|
{
|
||||||
sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
|
inet_ntop(AF_INET, &in, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
sprintf(errstr, _("duplicate dhcp-host IP address %s"),
|
||||||
|
daemon->addrbuff);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4163,13 +4186,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
new->interface = opt_string_alloc(split(comma));
|
new->interface = opt_string_alloc(split(comma));
|
||||||
new->iface_index = 0;
|
new->iface_index = 0;
|
||||||
if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
|
if (comma && inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
|
||||||
{
|
{
|
||||||
new->next = daemon->relay4;
|
new->next = daemon->relay4;
|
||||||
daemon->relay4 = new;
|
daemon->relay4 = new;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
|
else if (comma && inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
|
||||||
{
|
{
|
||||||
new->next = daemon->relay6;
|
new->next = daemon->relay6;
|
||||||
daemon->relay6 = new;
|
daemon->relay6 = new;
|
||||||
@@ -5005,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;
|
||||||
|
|
||||||
@@ -5029,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 */
|
||||||
@@ -5089,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5214,7 +5261,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
daemon = opt_malloc(sizeof(struct daemon));
|
daemon = opt_malloc(sizeof(struct daemon));
|
||||||
memset(daemon, 0, sizeof(struct daemon));
|
memset(daemon, 0, sizeof(struct daemon));
|
||||||
daemon->namebuff = buff;
|
daemon->namebuff = buff;
|
||||||
|
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
||||||
|
|
||||||
/* Set defaults - everything else is zero or NULL */
|
/* Set defaults - everything else is zero or NULL */
|
||||||
daemon->cachesize = CACHESIZ;
|
daemon->cachesize = CACHESIZ;
|
||||||
daemon->ftabsize = FTABSIZ;
|
daemon->ftabsize = FTABSIZ;
|
||||||
|
|||||||
+26
-26
@@ -20,13 +20,13 @@
|
|||||||
|
|
||||||
#define LOG(...) \
|
#define LOG(...) \
|
||||||
do { \
|
do { \
|
||||||
my_syslog(LOG_WARNING, __VA_ARGS__); \
|
my_syslog(LOG_DEBUG, __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ASSERT(condition) \
|
#define ASSERT(condition) \
|
||||||
do { \
|
do { \
|
||||||
if (!(condition)) \
|
if (!(condition)) \
|
||||||
LOG("[pattern.c:%d] Assertion failure: %s", __LINE__, #condition); \
|
my_syslog(LOG_ERR, _("[pattern.c:%d] Assertion failure: %s"), __LINE__, #condition); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,8 +66,8 @@ static int is_string_matching_glob_pattern(
|
|||||||
pattern_character -= 'a' - 'A';
|
pattern_character -= 'a' - 'A';
|
||||||
if (pattern_character == '*')
|
if (pattern_character == '*')
|
||||||
{
|
{
|
||||||
// zero-or-more-character wildcard
|
/* zero-or-more-character wildcard */
|
||||||
// Try to match at value_index, otherwise restart at value_index + 1 next.
|
/* Try to match at value_index, otherwise restart at value_index + 1 next. */
|
||||||
next_pattern_index = pattern_index;
|
next_pattern_index = pattern_index;
|
||||||
pattern_index++;
|
pattern_index++;
|
||||||
if (value_index < num_value_bytes)
|
if (value_index < num_value_bytes)
|
||||||
@@ -78,7 +78,7 @@ static int is_string_matching_glob_pattern(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// ordinary character
|
/* ordinary character */
|
||||||
if (value_index < num_value_bytes)
|
if (value_index < num_value_bytes)
|
||||||
{
|
{
|
||||||
char value_character = value[value_index];
|
char value_character = value[value_index];
|
||||||
@@ -139,7 +139,7 @@ int is_valid_dns_name(const char *value)
|
|||||||
(*c < 'A' || *c > 'Z') &&
|
(*c < 'A' || *c > 'Z') &&
|
||||||
(*c < 'a' || *c > 'z'))
|
(*c < 'a' || *c > 'z'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Invalid character %c.", *c);
|
LOG(_("Invalid DNS name: Invalid character %c."), *c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c)
|
if (*c)
|
||||||
@@ -148,12 +148,12 @@ int is_valid_dns_name(const char *value)
|
|||||||
{
|
{
|
||||||
if (!*c || *c == '.')
|
if (!*c || *c == '.')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Empty label.");
|
LOG(_("Invalid DNS name: Empty label."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c == '-')
|
if (*c == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Label starts with hyphen.");
|
LOG(_("Invalid DNS name: Label starts with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
label = c;
|
label = c;
|
||||||
@@ -167,13 +167,13 @@ int is_valid_dns_name(const char *value)
|
|||||||
{
|
{
|
||||||
if (c[-1] == '-')
|
if (c[-1] == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Label ends with hyphen.");
|
LOG(_("Invalid DNS name: Label ends with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t num_label_bytes = (size_t) (c - label);
|
size_t num_label_bytes = (size_t) (c - label);
|
||||||
if (num_label_bytes > 63)
|
if (num_label_bytes > 63)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Label is too long (%zu).", num_label_bytes);
|
LOG(_("Invalid DNS name: Label is too long (%zu)."), num_label_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
num_labels++;
|
num_labels++;
|
||||||
@@ -181,12 +181,12 @@ int is_valid_dns_name(const char *value)
|
|||||||
{
|
{
|
||||||
if (num_labels < 2)
|
if (num_labels < 2)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Not enough labels (%zu).", num_labels);
|
LOG(_("Invalid DNS name: Not enough labels (%zu)."), num_labels);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (is_label_numeric)
|
if (is_label_numeric)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: Final label is fully numeric.");
|
LOG(_("Invalid DNS name: Final label is fully numeric."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_label_bytes == 5 &&
|
if (num_label_bytes == 5 &&
|
||||||
@@ -196,12 +196,12 @@ int is_valid_dns_name(const char *value)
|
|||||||
(label[3] == 'a' || label[3] == 'A') &&
|
(label[3] == 'a' || label[3] == 'A') &&
|
||||||
(label[4] == 'l' || label[4] == 'L'))
|
(label[4] == 'l' || label[4] == 'L'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name: \"local\" pseudo-TLD.");
|
LOG(_("Invalid DNS name: \"local\" pseudo-TLD."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_bytes < 1 || num_bytes > 253)
|
if (num_bytes < 1 || num_bytes > 253)
|
||||||
{
|
{
|
||||||
LOG("DNS name has invalid length (%zu).", num_bytes);
|
LOG(_("DNS name has invalid length (%zu)."), num_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -249,13 +249,13 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
for (const char *c = value;; c++)
|
for (const char *c = value;; c++)
|
||||||
{
|
{
|
||||||
if (*c &&
|
if (*c &&
|
||||||
*c != '*' && // Wildcard.
|
*c != '*' && /* Wildcard. */
|
||||||
*c != '-' && *c != '.' &&
|
*c != '-' && *c != '.' &&
|
||||||
(*c < '0' || *c > '9') &&
|
(*c < '0' || *c > '9') &&
|
||||||
(*c < 'A' || *c > 'Z') &&
|
(*c < 'A' || *c > 'Z') &&
|
||||||
(*c < 'a' || *c > 'z'))
|
(*c < 'a' || *c > 'z'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Invalid character %c.", *c);
|
LOG(_("Invalid DNS name pattern: Invalid character %c."), *c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c && *c != '*')
|
if (*c && *c != '*')
|
||||||
@@ -264,12 +264,12 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (!*c || *c == '.')
|
if (!*c || *c == '.')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Empty label.");
|
LOG(_("Invalid DNS name pattern: Empty label."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*c == '-')
|
if (*c == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Label starts with hyphen.");
|
LOG(_("Invalid DNS name pattern: Label starts with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
label = c;
|
label = c;
|
||||||
@@ -282,7 +282,7 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (num_wildcards >= 2)
|
if (num_wildcards >= 2)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Wildcard character used more than twice per label.");
|
LOG(_("Invalid DNS name pattern: Wildcard character used more than twice per label."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
num_wildcards++;
|
num_wildcards++;
|
||||||
@@ -292,13 +292,13 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (c[-1] == '-')
|
if (c[-1] == '-')
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Label ends with hyphen.");
|
LOG(_("Invalid DNS name pattern: Label ends with hyphen."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t num_label_bytes = (size_t) (c - label) - num_wildcards;
|
size_t num_label_bytes = (size_t) (c - label) - num_wildcards;
|
||||||
if (num_label_bytes > 63)
|
if (num_label_bytes > 63)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Label is too long (%zu).", num_label_bytes);
|
LOG(_("Invalid DNS name pattern: Label is too long (%zu)."), num_label_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
num_labels++;
|
num_labels++;
|
||||||
@@ -306,17 +306,17 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
{
|
{
|
||||||
if (num_labels < 2)
|
if (num_labels < 2)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Not enough labels (%zu).", num_labels);
|
LOG(_("Invalid DNS name pattern: Not enough labels (%zu)."), num_labels);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_wildcards != 0 || previous_label_has_wildcard)
|
if (num_wildcards != 0 || previous_label_has_wildcard)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Wildcard within final two labels.");
|
LOG(_("Invalid DNS name pattern: Wildcard within final two labels."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (is_label_numeric)
|
if (is_label_numeric)
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: Final label is fully numeric.");
|
LOG(_("Invalid DNS name pattern: Final label is fully numeric."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_label_bytes == 5 &&
|
if (num_label_bytes == 5 &&
|
||||||
@@ -326,12 +326,12 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
(label[3] == 'a' || label[3] == 'A') &&
|
(label[3] == 'a' || label[3] == 'A') &&
|
||||||
(label[4] == 'l' || label[4] == 'L'))
|
(label[4] == 'l' || label[4] == 'L'))
|
||||||
{
|
{
|
||||||
LOG("Invalid DNS name pattern: \"local\" pseudo-TLD.");
|
LOG(_("Invalid DNS name pattern: \"local\" pseudo-TLD."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (num_bytes < 1 || num_bytes > 253)
|
if (num_bytes < 1 || num_bytes > 253)
|
||||||
{
|
{
|
||||||
LOG("DNS name pattern has invalid length after removing wildcards (%zu).", num_bytes);
|
LOG(_("DNS name pattern has invalid length after removing wildcards (%zu)."), num_bytes);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+324
-277
@@ -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);
|
||||||
|
/* 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,15 +552,21 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
#else
|
#else
|
||||||
(void)ipsets; /* unused */
|
(void)ipsets; /* unused */
|
||||||
#endif
|
#endif
|
||||||
|
int found = 0, cname_count = CNAME_CHAIN;
|
||||||
|
struct crec *cpp = NULL;
|
||||||
|
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
int cname_short = 0;
|
||||||
|
#endif
|
||||||
|
unsigned long cttl = ULONG_MAX, attl;
|
||||||
|
|
||||||
cache_start_insert();
|
cache_start_insert();
|
||||||
|
|
||||||
/* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
|
/* 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_LOG) || option_bool(OPT_DNSSEC_VALID))
|
if (daemon->doctors || option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
searched_soa = 1;
|
searched_soa = 1;
|
||||||
ttl = find_soa(header, qlen, name, doctored);
|
ttl = find_soa(header, qlen, doctored);
|
||||||
|
|
||||||
if (*doctored)
|
if (*doctored)
|
||||||
{
|
{
|
||||||
@@ -567,159 +574,46 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
return 0;
|
return 0;
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
for (i = 0; i < ntohs(header->ancount); i++)
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
if (daemon->rr_status[i] != 0)
|
if (daemon->rr_status[j] != 0)
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go through the questions. */
|
namep = p = (unsigned char *)(header+1);
|
||||||
p = (unsigned char *)(header+1);
|
|
||||||
|
|
||||||
for (i = ntohs(header->qdcount); i != 0; i--)
|
if (ntohs(header->qdcount) != 1 || !extract_name(header, qlen, &p, name, 1, 4))
|
||||||
{
|
return 0; /* bad packet */
|
||||||
int found = 0, cname_count = CNAME_CHAIN;
|
|
||||||
struct crec *cpp = NULL;
|
GETSHORT(qtype, p);
|
||||||
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
GETSHORT(qclass, p);
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
int cname_short = 0;
|
if (qclass != C_IN)
|
||||||
#endif
|
return 0;
|
||||||
unsigned long cttl = ULONG_MAX, attl;
|
|
||||||
|
/* PTRs: we chase CNAMEs here, since we have no way to
|
||||||
namep = p;
|
represent them in the cache. */
|
||||||
if (!extract_name(header, qlen, &p, name, 1, 4))
|
if (qtype == T_PTR)
|
||||||
return 0; /* bad packet */
|
{
|
||||||
|
int insert = 1, name_encoding = in_arpa_name_2_addr(name, &addr);
|
||||||
GETSHORT(qtype, p);
|
|
||||||
GETSHORT(qclass, p);
|
|
||||||
|
|
||||||
if (qclass != C_IN)
|
if (!(flags & F_NXDOMAIN))
|
||||||
continue;
|
|
||||||
|
|
||||||
/* PTRs: we chase CNAMEs here, since we have no way to
|
|
||||||
represent them in the cache. */
|
|
||||||
if (qtype == T_PTR)
|
|
||||||
{
|
|
||||||
int name_encoding = in_arpa_name_2_addr(name, &addr);
|
|
||||||
|
|
||||||
if (!name_encoding)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(flags & F_NXDOMAIN))
|
|
||||||
{
|
|
||||||
cname_loop:
|
|
||||||
if (!(p1 = skip_questions(header, qlen)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (j = 0; j < ntohs(header->ancount); j++)
|
|
||||||
{
|
|
||||||
int secflag = 0;
|
|
||||||
unsigned char *tmp = namep;
|
|
||||||
/* 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 */
|
|
||||||
|
|
||||||
GETSHORT(aqtype, p1);
|
|
||||||
GETSHORT(aqclass, p1);
|
|
||||||
GETLONG(attl, p1);
|
|
||||||
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
|
|
||||||
{
|
|
||||||
(p1) -= 4;
|
|
||||||
PUTLONG(daemon->max_ttl, p1);
|
|
||||||
}
|
|
||||||
GETSHORT(ardlen, p1);
|
|
||||||
endrr = p1+ardlen;
|
|
||||||
|
|
||||||
/* TTL of record is minimum of CNAMES and PTR */
|
|
||||||
if (attl < cttl)
|
|
||||||
cttl = attl;
|
|
||||||
|
|
||||||
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
|
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && daemon->rr_status[j] != 0)
|
|
||||||
{
|
|
||||||
/* validated RR anywhere in CNAME chain, don't cache. */
|
|
||||||
if (cname_short || aqtype == T_CNAME)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
secflag = F_DNSSECOK;
|
|
||||||
/* limit TTL based on signature. */
|
|
||||||
if (daemon->rr_status[j] < cttl)
|
|
||||||
cttl = daemon->rr_status[j];
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (aqtype == T_CNAME)
|
|
||||||
{
|
|
||||||
if (!cname_count--)
|
|
||||||
return 0; /* looped CNAMES, we can't cache. */
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
cname_short = 1;
|
|
||||||
#endif
|
|
||||||
goto cname_loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_insert(name, &addr, C_IN, now, cttl, name_encoding | secflag | F_REVERSE);
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
p1 = endrr;
|
|
||||||
if (!CHECK_LEN(header, p1, qlen, 0))
|
|
||||||
return 0; /* bad packet */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found && !option_bool(OPT_NO_NEG))
|
|
||||||
{
|
|
||||||
if (!searched_soa)
|
|
||||||
{
|
|
||||||
searched_soa = 1;
|
|
||||||
ttl = find_soa(header, qlen, NULL, doctored);
|
|
||||||
}
|
|
||||||
if (ttl)
|
|
||||||
cache_insert(NULL, &addr, C_IN, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* everything other than PTR */
|
cname_loop:
|
||||||
struct crec *newc;
|
|
||||||
int addrlen = 0;
|
|
||||||
|
|
||||||
if (qtype == T_A)
|
|
||||||
{
|
|
||||||
addrlen = INADDRSZ;
|
|
||||||
flags |= F_IPV4;
|
|
||||||
}
|
|
||||||
else if (qtype == T_AAAA)
|
|
||||||
{
|
|
||||||
addrlen = IN6ADDRSZ;
|
|
||||||
flags |= F_IPV6;
|
|
||||||
}
|
|
||||||
else if (qtype == T_SRV)
|
|
||||||
flags |= F_SRV;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cname_loop1:
|
|
||||||
if (!(p1 = skip_questions(header, qlen)))
|
if (!(p1 = skip_questions(header, qlen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (j = 0; j < ntohs(header->ancount); j++)
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
{
|
{
|
||||||
int secflag = 0;
|
int secflag = 0;
|
||||||
|
|
||||||
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
if (!(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;
|
||||||
@@ -728,128 +622,281 @@ 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))
|
/* TTL of record is minimum of CNAMES and PTR */
|
||||||
|
if (attl < cttl)
|
||||||
|
cttl = attl;
|
||||||
|
|
||||||
|
if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
|
||||||
{
|
{
|
||||||
#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. */
|
||||||
|
if (cname_short || aqtype == T_CNAME)
|
||||||
|
insert = 0;
|
||||||
|
|
||||||
secflag = F_DNSSECOK;
|
secflag = F_DNSSECOK;
|
||||||
|
/* limit TTL based on signature. */
|
||||||
/* limit TTl based on sig. */
|
if (daemon->rr_status[j] < cttl)
|
||||||
if (daemon->rr_status[j] < attl)
|
cttl = daemon->rr_status[j];
|
||||||
attl = daemon->rr_status[j];
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (aqtype == T_CNAME)
|
||||||
|
log_query(secflag | F_CNAME | F_FORWARD | F_UPSTREAM, name, NULL, NULL);
|
||||||
|
|
||||||
|
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--)
|
||||||
return 0; /* looped CNAMES */
|
return 0; /* looped CNAMES, we can't cache. */
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
if ((newc = cache_insert(name, NULL, C_IN, now, attl, F_CNAME | F_FORWARD | secflag)))
|
cname_short = 1;
|
||||||
{
|
|
||||||
newc->addr.cname.target.cache = NULL;
|
|
||||||
newc->addr.cname.is_name_ptr = 0;
|
|
||||||
if (cpp)
|
|
||||||
{
|
|
||||||
next_uid(newc);
|
|
||||||
cpp->addr.cname.target.cache = newc;
|
|
||||||
cpp->addr.cname.uid = newc->uid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cpp = newc;
|
|
||||||
if (attl < cttl)
|
|
||||||
cttl = attl;
|
|
||||||
|
|
||||||
namep = p1;
|
|
||||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
goto cname_loop1;
|
|
||||||
}
|
|
||||||
else if (!(flags & F_NXDOMAIN))
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
|
|
||||||
if (flags & F_SRV)
|
|
||||||
{
|
|
||||||
unsigned char *tmp = namep;
|
|
||||||
|
|
||||||
if (!CHECK_LEN(header, p1, qlen, 6))
|
|
||||||
return 0; /* bad packet */
|
|
||||||
GETSHORT(addr.srv.priority, p1);
|
|
||||||
GETSHORT(addr.srv.weight, p1);
|
|
||||||
GETSHORT(addr.srv.srvport, p1);
|
|
||||||
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
|
||||||
return 0;
|
|
||||||
addr.srv.targetlen = strlen(name) + 1; /* include terminating zero */
|
|
||||||
if (!(addr.srv.target = blockdata_alloc(name, addr.srv.targetlen)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* we overwrote the original name, so get it back here. */
|
|
||||||
if (!extract_name(header, qlen, &tmp, name, 1, 0))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* copy address into aligned storage */
|
|
||||||
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
|
||||||
return 0; /* bad packet */
|
|
||||||
memcpy(&addr, p1, addrlen);
|
|
||||||
|
|
||||||
/* check for returned address in private space */
|
|
||||||
if (check_rebind)
|
|
||||||
{
|
|
||||||
if ((flags & F_IPV4) &&
|
|
||||||
private_net(addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if ((flags & F_IPV6) &&
|
|
||||||
private_net6(&addr.addr6, !option_bool(OPT_LOCAL_REBIND)))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_IPSET
|
|
||||||
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
|
||||||
{
|
|
||||||
ipsets_cur = ipsets;
|
|
||||||
while (*ipsets_cur)
|
|
||||||
{
|
|
||||||
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur);
|
|
||||||
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
goto cname_loop;
|
||||||
|
}
|
||||||
newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
|
|
||||||
if (newc && cpp)
|
found = 1;
|
||||||
|
|
||||||
|
if (!name_encoding)
|
||||||
|
log_query(secflag | F_FORWARD | F_UPSTREAM, name, NULL, querystr(NULL, aqtype));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_query(name_encoding | secflag | F_REVERSE | F_UPSTREAM, name, &addr, NULL);
|
||||||
|
if (insert)
|
||||||
|
cache_insert(name, &addr, C_IN, now, cttl, name_encoding | secflag | F_REVERSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p1 = endrr;
|
||||||
|
if (!CHECK_LEN(header, p1, qlen, 0))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found && !option_bool(OPT_NO_NEG))
|
||||||
|
{
|
||||||
|
if (!searched_soa)
|
||||||
|
{
|
||||||
|
searched_soa = 1;
|
||||||
|
ttl = find_soa(header, qlen, doctored);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* everything other than PTR */
|
||||||
|
struct crec *newc;
|
||||||
|
int addrlen = 0, insert = 1;
|
||||||
|
|
||||||
|
if (qtype == T_A)
|
||||||
|
{
|
||||||
|
addrlen = INADDRSZ;
|
||||||
|
flags |= F_IPV4;
|
||||||
|
}
|
||||||
|
else if (qtype == T_AAAA)
|
||||||
|
{
|
||||||
|
addrlen = IN6ADDRSZ;
|
||||||
|
flags |= F_IPV6;
|
||||||
|
}
|
||||||
|
else if (qtype == T_SRV)
|
||||||
|
flags |= F_SRV;
|
||||||
|
else
|
||||||
|
insert = 0; /* NOTE: do not cache data from CNAME queries. */
|
||||||
|
|
||||||
|
cname_loop1:
|
||||||
|
if (!(p1 = skip_questions(header, qlen)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (j = 0; j < ntohs(header->ancount); j++)
|
||||||
|
{
|
||||||
|
int secflag = 0;
|
||||||
|
|
||||||
|
if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
GETSHORT(aqtype, p1);
|
||||||
|
GETSHORT(aqclass, p1);
|
||||||
|
GETLONG(attl, p1);
|
||||||
|
if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
|
||||||
|
{
|
||||||
|
(p1) -= 4;
|
||||||
|
PUTLONG(daemon->max_ttl, p1);
|
||||||
|
}
|
||||||
|
GETSHORT(ardlen, p1);
|
||||||
|
endrr = p1+ardlen;
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && !no_cache_dnssec && daemon->rr_status[j] != 0)
|
||||||
|
{
|
||||||
|
secflag = F_DNSSECOK;
|
||||||
|
|
||||||
|
/* limit TTl based on sig. */
|
||||||
|
if (daemon->rr_status[j] < attl)
|
||||||
|
attl = daemon->rr_status[j];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (aqtype == T_CNAME)
|
||||||
|
{
|
||||||
|
if (!cname_count--)
|
||||||
|
return 0; /* looped CNAMES */
|
||||||
|
|
||||||
|
log_query(secflag | F_CNAME | F_FORWARD | F_UPSTREAM, name, NULL, NULL);
|
||||||
|
|
||||||
|
if (insert)
|
||||||
|
{
|
||||||
|
if ((newc = cache_insert(name, NULL, C_IN, now, attl, F_CNAME | F_FORWARD | secflag)))
|
||||||
|
{
|
||||||
|
newc->addr.cname.target.cache = NULL;
|
||||||
|
newc->addr.cname.is_name_ptr = 0;
|
||||||
|
if (cpp)
|
||||||
{
|
{
|
||||||
next_uid(newc);
|
next_uid(newc);
|
||||||
cpp->addr.cname.target.cache = newc;
|
cpp->addr.cname.target.cache = newc;
|
||||||
cpp->addr.cname.uid = newc->uid;
|
cpp->addr.cname.uid = newc->uid;
|
||||||
}
|
}
|
||||||
cpp = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpp = newc;
|
||||||
|
if (attl < cttl)
|
||||||
|
cttl = attl;
|
||||||
}
|
}
|
||||||
|
|
||||||
p1 = endrr;
|
namep = p1;
|
||||||
if (!CHECK_LEN(header, p1, qlen, 0))
|
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||||
return 0; /* bad packet */
|
return 0;
|
||||||
|
|
||||||
|
goto cname_loop1;
|
||||||
|
}
|
||||||
|
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, querystr(NULL, aqtype));
|
||||||
|
}
|
||||||
|
else if (!(flags & F_NXDOMAIN))
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
|
||||||
|
if (flags & F_SRV)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = namep;
|
||||||
|
|
||||||
|
if (!CHECK_LEN(header, p1, qlen, 6))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
GETSHORT(addr.srv.priority, p1);
|
||||||
|
GETSHORT(addr.srv.weight, p1);
|
||||||
|
GETSHORT(addr.srv.srvport, p1);
|
||||||
|
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||||
|
return 0;
|
||||||
|
addr.srv.targetlen = strlen(name) + 1; /* include terminating zero */
|
||||||
|
if (!(addr.srv.target = blockdata_alloc(name, addr.srv.targetlen)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* we overwrote the original name, so get it back here. */
|
||||||
|
if (!extract_name(header, qlen, &tmp, name, 1, 0))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (flags & (F_IPV4 | F_IPV6))
|
||||||
|
{
|
||||||
|
/* copy address into aligned storage */
|
||||||
|
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
memcpy(&addr, p1, addrlen);
|
||||||
|
|
||||||
|
/* check for returned address in private space */
|
||||||
|
if (check_rebind)
|
||||||
|
{
|
||||||
|
if ((flags & F_IPV4) &&
|
||||||
|
private_net(addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((flags & F_IPV6) &&
|
||||||
|
private_net6(&addr.addr6, !option_bool(OPT_LOCAL_REBIND)))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_IPSET
|
||||||
|
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
||||||
|
{
|
||||||
|
ipsets_cur = ipsets;
|
||||||
|
while (*ipsets_cur)
|
||||||
|
{
|
||||||
|
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur);
|
||||||
|
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insert)
|
||||||
|
{
|
||||||
|
newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
|
||||||
|
if (newc && cpp)
|
||||||
|
{
|
||||||
|
next_uid(newc);
|
||||||
|
cpp->addr.cname.target.cache = newc;
|
||||||
|
cpp->addr.cname.uid = newc->uid;
|
||||||
|
}
|
||||||
|
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, querystr(NULL, aqtype));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found && !option_bool(OPT_NO_NEG))
|
p1 = endrr;
|
||||||
|
if (!CHECK_LEN(header, p1, qlen, 0))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found && !option_bool(OPT_NO_NEG))
|
||||||
|
{
|
||||||
|
if (!searched_soa)
|
||||||
{
|
{
|
||||||
if (!searched_soa)
|
searched_soa = 1;
|
||||||
|
ttl = find_soa(header, qlen, doctored);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there's no SOA to get the TTL from, but there is a CNAME
|
||||||
|
pointing at this, inherit its TTL */
|
||||||
|
if (ttl || cpp)
|
||||||
|
{
|
||||||
|
if (ttl == 0)
|
||||||
|
ttl = cttl;
|
||||||
|
|
||||||
|
log_query(F_UPSTREAM | F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0), name, NULL, NULL);
|
||||||
|
|
||||||
|
if (insert)
|
||||||
{
|
{
|
||||||
searched_soa = 1;
|
newc = cache_insert(name, NULL, C_IN, now, ttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
||||||
ttl = find_soa(header, qlen, NULL, doctored);
|
|
||||||
}
|
|
||||||
/* If there's no SOA to get the TTL from, but there is a CNAME
|
|
||||||
pointing at this, inherit its TTL */
|
|
||||||
if (ttl || cpp)
|
|
||||||
{
|
|
||||||
newc = cache_insert(name, NULL, C_IN, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
|
||||||
if (newc && cpp)
|
if (newc && cpp)
|
||||||
{
|
{
|
||||||
next_uid(newc);
|
next_uid(newc);
|
||||||
|
|||||||
+59
-37
@@ -372,9 +372,22 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
{
|
{
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
|
const char *via;
|
||||||
subnet_addr.s_addr ? _("with subnet selector") : _("via"),
|
if (subnet_addr.s_addr)
|
||||||
subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
|
{
|
||||||
|
via = _("with subnet selector");
|
||||||
|
inet_ntop(AF_INET, &subnet_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
via = _("via");
|
||||||
|
if (mess->giaddr.s_addr)
|
||||||
|
inet_ntop(AF_INET, &mess->giaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
else
|
||||||
|
safe_strncpy(daemon->addrbuff, iface_name, ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
|
||||||
|
via, daemon->addrbuff);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,13 +396,19 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
struct dhcp_context *context_tmp;
|
struct dhcp_context *context_tmp;
|
||||||
for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
|
for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
|
||||||
{
|
{
|
||||||
strcpy(daemon->namebuff, inet_ntoa(context_tmp->start));
|
inet_ntop(AF_INET, &context_tmp->start, daemon->namebuff, MAXDNAME);
|
||||||
if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
|
if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
|
{
|
||||||
ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask));
|
inet_ntop(AF_INET, &context_tmp->netmask, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
|
||||||
|
ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
|
{
|
||||||
ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end));
|
inet_ntop(AF_INET, &context_tmp->end, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
|
||||||
|
ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,8 +1050,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
config->addr.s_addr == option_addr(opt).s_addr)
|
config->addr.s_addr == option_addr(opt).s_addr)
|
||||||
{
|
{
|
||||||
prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
|
prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
|
||||||
|
inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
|
||||||
inet_ntoa(config->addr), daemon->dhcp_buff);
|
daemon->addrbuff, daemon->dhcp_buff);
|
||||||
config->flags |= CONFIG_DECLINED;
|
config->flags |= CONFIG_DECLINED;
|
||||||
config->decline_time = now;
|
config->decline_time = now;
|
||||||
}
|
}
|
||||||
@@ -1078,7 +1098,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
if (have_config(config, CONFIG_ADDR))
|
if (have_config(config, CONFIG_ADDR))
|
||||||
{
|
{
|
||||||
char *addrs = inet_ntoa(config->addr);
|
inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
|
||||||
if ((ltmp = lease_find_by_addr(config->addr)) &&
|
if ((ltmp = lease_find_by_addr(config->addr)) &&
|
||||||
ltmp != lease &&
|
ltmp != lease &&
|
||||||
@@ -1088,7 +1108,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
|
unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
|
||||||
ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
|
ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
|
||||||
addrs, print_mac(daemon->namebuff, mac, len));
|
daemon->addrbuff, print_mac(daemon->namebuff, mac, len));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1097,10 +1117,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if (context->router.s_addr == config->addr.s_addr)
|
if (context->router.s_addr == config->addr.s_addr)
|
||||||
break;
|
break;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs);
|
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), daemon->addrbuff);
|
||||||
else if (have_config(config, CONFIG_DECLINED) &&
|
else if (have_config(config, CONFIG_DECLINED) &&
|
||||||
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
|
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
|
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), daemon->addrbuff);
|
||||||
else
|
else
|
||||||
conf = config->addr;
|
conf = config->addr;
|
||||||
}
|
}
|
||||||
@@ -1303,9 +1323,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
a lease from one of it's MACs to give the address to another. */
|
a lease from one of it's MACs to give the address to another. */
|
||||||
if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
|
if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
|
||||||
{
|
{
|
||||||
|
inet_ntop(AF_INET, <mp->addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
|
my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
|
||||||
print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
|
print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
|
||||||
inet_ntoa(ltmp->addr));
|
daemon->addrbuff);
|
||||||
lease = ltmp;
|
lease = ltmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1674,42 +1695,40 @@ static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
|
|||||||
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
||||||
int mac_len, char *interface, char *string, char *err, u32 xid)
|
int mac_len, char *interface, char *string, char *err, u32 xid)
|
||||||
{
|
{
|
||||||
struct in_addr a;
|
|
||||||
|
|
||||||
if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
|
if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* addr may be misaligned */
|
daemon->addrbuff[0] = 0;
|
||||||
if (addr)
|
if (addr)
|
||||||
memcpy(&a, addr, sizeof(a));
|
inet_ntop(AF_INET, addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
|
||||||
print_mac(daemon->namebuff, ext_mac, mac_len);
|
print_mac(daemon->namebuff, ext_mac, mac_len);
|
||||||
|
|
||||||
if(option_bool(OPT_LOG_OPTS))
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
|
my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
|
||||||
ntohl(xid),
|
ntohl(xid),
|
||||||
type,
|
|
||||||
interface,
|
|
||||||
addr ? inet_ntoa(a) : "",
|
|
||||||
addr ? " " : "",
|
|
||||||
daemon->namebuff,
|
|
||||||
string ? string : "",
|
|
||||||
err ? err : "");
|
|
||||||
else
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
|
|
||||||
type,
|
type,
|
||||||
interface,
|
interface,
|
||||||
addr ? inet_ntoa(a) : "",
|
daemon->addrbuff,
|
||||||
addr ? " " : "",
|
addr ? " " : "",
|
||||||
daemon->namebuff,
|
daemon->namebuff,
|
||||||
string ? string : "",
|
string ? string : "",
|
||||||
err ? err : "");
|
err ? err : "");
|
||||||
|
else
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
|
||||||
|
type,
|
||||||
|
interface,
|
||||||
|
daemon->addrbuff,
|
||||||
|
addr ? " " : "",
|
||||||
|
daemon->namebuff,
|
||||||
|
string ? string : "",
|
||||||
|
err ? err : "");
|
||||||
|
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
if (!strcmp(type, "DHCPACK"))
|
if (!strcmp(type, "DHCPACK"))
|
||||||
ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
|
ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
|
||||||
else if (!strcmp(type, "DHCPRELEASE"))
|
else if (!strcmp(type, "DHCPRELEASE"))
|
||||||
ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
|
ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1861,7 +1880,10 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id
|
|||||||
if (option_bool(OPT_LOG_OPTS))
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
{
|
{
|
||||||
if (mess->siaddr.s_addr != 0)
|
if (mess->siaddr.s_addr != 0)
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr));
|
{
|
||||||
|
inet_ntop(AF_INET, &mess->siaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), daemon->addrbuff);
|
||||||
|
}
|
||||||
|
|
||||||
if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
|
if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
|
my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
|
||||||
|
|||||||
+2
-1
@@ -761,7 +761,8 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
|
|||||||
len = snprintf(mess->message, MAXMESSAGE, message, file, errstr);
|
len = snprintf(mess->message, MAXMESSAGE, message, file, errstr);
|
||||||
ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
|
ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
|
||||||
|
|
||||||
my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
|
if (err != ERR_FNF || !option_bool(OPT_QUIET_TFTP))
|
||||||
|
my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-37
@@ -21,7 +21,6 @@
|
|||||||
#include <libubus.h>
|
#include <libubus.h>
|
||||||
|
|
||||||
static struct blob_buf b;
|
static struct blob_buf b;
|
||||||
static int notify;
|
|
||||||
static int error_logged = 0;
|
static int error_logged = 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,
|
||||||
@@ -78,17 +77,16 @@ static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
|
|||||||
(void)ctx;
|
(void)ctx;
|
||||||
|
|
||||||
my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
|
my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
|
||||||
notify = obj->has_subscribers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ubus_destroy(struct ubus_context *ubus)
|
static void ubus_destroy(struct ubus_context *ubus)
|
||||||
{
|
{
|
||||||
// Forces re-initialization when we're reusing the same definitions later on.
|
|
||||||
ubus_object.id = 0;
|
|
||||||
ubus_object_type.id = 0;
|
|
||||||
|
|
||||||
ubus_free(ubus);
|
ubus_free(ubus);
|
||||||
daemon->ubus = NULL;
|
daemon->ubus = NULL;
|
||||||
|
|
||||||
|
/* Forces re-initialization when we're reusing the same definitions later on. */
|
||||||
|
ubus_object.id = 0;
|
||||||
|
ubus_object_type.id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ubus_disconnect_cb(struct ubus_context *ubus)
|
static void ubus_disconnect_cb(struct ubus_context *ubus)
|
||||||
@@ -173,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)
|
||||||
@@ -183,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
|
||||||
@@ -307,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 || !notify)
|
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 || !notify)
|
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 || !notify)
|
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 */
|
||||||
Reference in new issue
Block a user