mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
32
Commits
v2.86test4
...
v2.86test6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8389b943d3 | ||
|
|
f2266d9678 | ||
|
|
56bd806978 | ||
|
|
ac7eeea44d | ||
|
|
b741059549 | ||
|
|
cbd984287f | ||
|
|
32e15c3f45 | ||
|
|
f0dc324e35 | ||
|
|
f83c6cf51a | ||
|
|
c068b3ae2f | ||
|
|
adf9dec1e6 | ||
|
|
767d9cbd96 | ||
|
|
e7ccd95c04 | ||
|
|
719f79a8fd | ||
|
|
96f6444958 | ||
|
|
df25f204ba | ||
|
|
8acdc3ede7 | ||
|
|
857b445522 | ||
|
|
5bcca1219a | ||
|
|
4558c26fcd | ||
|
|
a92c6d77dc | ||
|
|
0c95a5ff53 | ||
|
|
cb6d06bb54 | ||
|
|
3ef955c85a | ||
|
|
5e95c16c32 | ||
|
|
4205e2ebcf | ||
|
|
9d806c51c2 | ||
|
|
a38bb31727 | ||
|
|
8a1ef367e2 | ||
|
|
1291865c92 | ||
|
|
a9ebbee7b6 | ||
|
|
06df5ad7d0 |
No files matched your search
@@ -76,6 +76,12 @@ 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 then 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.
|
||||||
|
|
||||||
|
|
||||||
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.
|
||||||
|
|||||||
+25
-10
@@ -327,8 +327,8 @@ are re-written. So
|
|||||||
maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40
|
maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40
|
||||||
.TP
|
.TP
|
||||||
.B \-B, --bogus-nxdomain=<ipaddr>[/prefix]
|
.B \-B, --bogus-nxdomain=<ipaddr>[/prefix]
|
||||||
Transform replies which contain the IP specified address or subnet into "No such
|
Transform replies which contain the specified address or subnet into "No such
|
||||||
domain" replies. This is intended to counteract a devious move made by
|
domain" replies. IPv4 and IPv6 are supported. This is intended to counteract a devious move made by
|
||||||
Verisign in September 2003 when they started returning the address of
|
Verisign in September 2003 when they started returning the address of
|
||||||
an advertising web page in response to queries for unregistered names,
|
an advertising web page in response to queries for unregistered names,
|
||||||
instead of the correct NXDOMAIN response. This option tells dnsmasq to
|
instead of the correct NXDOMAIN response. This option tells dnsmasq to
|
||||||
@@ -336,7 +336,7 @@ fake the correct response when it sees this behaviour. As at Sept 2003
|
|||||||
the IP address being returned by Verisign is 64.94.110.11
|
the IP address being returned by Verisign is 64.94.110.11
|
||||||
.TP
|
.TP
|
||||||
.B --ignore-address=<ipaddr>[/prefix]
|
.B --ignore-address=<ipaddr>[/prefix]
|
||||||
Ignore replies to A-record queries which include the specified address or subnet.
|
Ignore replies to A or AAAA queries which include the specified address or subnet.
|
||||||
No error is generated, dnsmasq simply continues to listen for another reply.
|
No error is generated, dnsmasq simply continues to listen for another reply.
|
||||||
This is useful to defeat blocking strategies which rely on quickly supplying a
|
This is useful to defeat blocking strategies which rely on quickly supplying a
|
||||||
forged answer to a DNS request for certain domain, before the correct answer can arrive.
|
forged answer to a DNS request for certain domain, before the correct answer can arrive.
|
||||||
@@ -460,13 +460,22 @@ repeated domain or ipaddr parts as required.
|
|||||||
More specific domains take precedence over less specific domains, so:
|
More specific domains take precedence over less specific domains, so:
|
||||||
.B --server=/google.com/1.2.3.4
|
.B --server=/google.com/1.2.3.4
|
||||||
.B --server=/www.google.com/2.3.4.5
|
.B --server=/www.google.com/2.3.4.5
|
||||||
will send queries for *.google.com to 1.2.3.4, except *www.google.com,
|
will send queries for google.com and gmail.google.com to 1.2.3.4, but www.google.com
|
||||||
which will go to 2.3.4.5
|
will go to 2.3.4.5
|
||||||
|
|
||||||
|
Matching of domains is normally done on complete labels, so /google.com/ matches google.com and www.google.com
|
||||||
|
but NOT supergoogle.com. This can be overridden with a * at the start of a pattern only: /*google.com/
|
||||||
|
will match google.com and www.google.com AND supergoogle.com. The non-wildcard form has priority, so
|
||||||
|
if /google.com/ and /*google.com/ are both specified then google.com and www.google.com will match /google.com/
|
||||||
|
and /*google.com/ will only match supergoogle.com.
|
||||||
|
|
||||||
|
For historical reasons, the pattern /.google.com/ is equivalent to /google.com/ if you wish to match any subdomain
|
||||||
|
of google.com but NOT google.com itself, use /*.google.com/
|
||||||
|
|
||||||
The special server address '#' means, "use the standard servers", so
|
The special server address '#' means, "use the standard servers", so
|
||||||
.B --server=/google.com/1.2.3.4
|
.B --server=/google.com/1.2.3.4
|
||||||
.B --server=/www.google.com/#
|
.B --server=/www.google.com/#
|
||||||
will send queries for *.google.com to 1.2.3.4, except *www.google.com which will
|
will send queries for google.com and its subdomains to 1.2.3.4, except www.google.com (and its subdomains) which will
|
||||||
be forwarded as usual.
|
be forwarded as usual.
|
||||||
|
|
||||||
Also permitted is a -S
|
Also permitted is a -S
|
||||||
@@ -696,7 +705,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.
|
||||||
@@ -1603,10 +1613,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.
|
||||||
@@ -2408,6 +2419,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
|
||||||
|
|||||||
+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;
|
||||||
}
|
}
|
||||||
@@ -401,6 +415,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
@@ -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
-13
@@ -1602,18 +1602,18 @@ int cache_make_stat(struct txt_record *t)
|
|||||||
case TXT_STAT_SERVERS:
|
case TXT_STAT_SERVERS:
|
||||||
/* sum counts from different records for same server */
|
/* sum counts from different records for same server */
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
serv->flags &= ~SERV_COUNTED;
|
serv->flags &= ~SERV_MARK;
|
||||||
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
if (!(serv->flags & SERV_COUNTED))
|
if (!(serv->flags & SERV_MARK))
|
||||||
{
|
{
|
||||||
char *new, *lenp;
|
char *new, *lenp;
|
||||||
int port, newlen, bytes_avail, bytes_needed;
|
int port, newlen, bytes_avail, bytes_needed;
|
||||||
unsigned int queries = 0, failed_queries = 0;
|
unsigned int queries = 0, failed_queries = 0;
|
||||||
for (serv1 = serv; serv1; serv1 = serv1->next)
|
for (serv1 = serv; serv1; serv1 = serv1->next)
|
||||||
if (!(serv1->flags & SERV_COUNTED) && sockaddr_isequal(&serv->addr, &serv1->addr))
|
if (!(serv1->flags & SERV_MARK) && sockaddr_isequal(&serv->addr, &serv1->addr))
|
||||||
{
|
{
|
||||||
serv1->flags |= SERV_COUNTED;
|
serv1->flags |= SERV_MARK;
|
||||||
queries += serv1->queries;
|
queries += serv1->queries;
|
||||||
failed_queries += serv1->failed_queries;
|
failed_queries += serv1->failed_queries;
|
||||||
}
|
}
|
||||||
@@ -1641,6 +1641,7 @@ int cache_make_stat(struct txt_record *t)
|
|||||||
}
|
}
|
||||||
t->txt = (unsigned char *)buff;
|
t->txt = (unsigned char *)buff;
|
||||||
t->len = p - buff;
|
t->len = p - buff;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1683,17 +1684,17 @@ void dump_cache(time_t now)
|
|||||||
|
|
||||||
/* sum counts from different records for same server */
|
/* sum counts from different records for same server */
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
serv->flags &= ~SERV_COUNTED;
|
serv->flags &= ~SERV_MARK;
|
||||||
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
if (!(serv->flags & SERV_COUNTED))
|
if (!(serv->flags & SERV_MARK))
|
||||||
{
|
{
|
||||||
int port;
|
int port;
|
||||||
unsigned int queries = 0, failed_queries = 0;
|
unsigned int queries = 0, failed_queries = 0;
|
||||||
for (serv1 = serv; serv1; serv1 = serv1->next)
|
for (serv1 = serv; serv1; serv1 = serv1->next)
|
||||||
if (!(serv1->flags & SERV_COUNTED) && sockaddr_isequal(&serv->addr, &serv1->addr))
|
if (!(serv1->flags & SERV_MARK) && sockaddr_isequal(&serv->addr, &serv1->addr))
|
||||||
{
|
{
|
||||||
serv1->flags |= SERV_COUNTED;
|
serv1->flags |= SERV_MARK;
|
||||||
queries += serv1->queries;
|
queries += serv1->queries;
|
||||||
failed_queries += serv1->failed_queries;
|
failed_queries += serv1->failed_queries;
|
||||||
}
|
}
|
||||||
@@ -1922,10 +1923,10 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
|
|||||||
else
|
else
|
||||||
sprintf(daemon->addrbuff, "%u", rcode);
|
sprintf(daemon->addrbuff, "%u", rcode);
|
||||||
|
|
||||||
if (addr->log.ede != -1)
|
if (addr->log.ede != EDE_UNSET)
|
||||||
{
|
{
|
||||||
extra = daemon->addrbuff;
|
extra = daemon->addrbuff;
|
||||||
sprintf(extra, " (EDE:%s)", edestr(addr->log.ede));
|
sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1973,10 +1974,10 @@ 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 != -1)
|
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));
|
||||||
}
|
}
|
||||||
source = "validation";
|
source = "validation";
|
||||||
dest = arg;
|
dest = arg;
|
||||||
@@ -2022,5 +2023,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);
|
||||||
}
|
}
|
||||||
+2
-4
@@ -222,7 +222,6 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
|
|
||||||
/* unlink and free anything still marked. */
|
/* unlink and free anything still marked. */
|
||||||
cleanup_servers();
|
cleanup_servers();
|
||||||
check_servers(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
@@ -277,7 +276,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
{
|
{
|
||||||
const char *str = NULL;
|
const char *str = NULL;
|
||||||
union mysockaddr addr, source_addr;
|
union mysockaddr addr, source_addr;
|
||||||
int flags = 0;
|
u16 flags = 0;
|
||||||
char interface[IF_NAMESIZE];
|
char interface[IF_NAMESIZE];
|
||||||
char *str_addr, *str_domain = NULL;
|
char *str_addr, *str_domain = NULL;
|
||||||
|
|
||||||
@@ -413,7 +412,6 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup_servers();
|
cleanup_servers();
|
||||||
check_servers(0);
|
|
||||||
|
|
||||||
if (dup)
|
if (dup)
|
||||||
free(dup);
|
free(dup);
|
||||||
@@ -713,7 +711,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
if (new_servers)
|
if (new_servers)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
|
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
|
||||||
check_servers();
|
check_servers(0);
|
||||||
if (option_bool(OPT_RELOAD))
|
if (option_bool(OPT_RELOAD))
|
||||||
clear_cache = 1;
|
clear_cache = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -85,7 +85,8 @@
|
|||||||
#define EDNS0_OPTION_NOMCPEID 65074 /* Nominum temporary assignment */
|
#define EDNS0_OPTION_NOMCPEID 65074 /* Nominum temporary assignment */
|
||||||
#define EDNS0_OPTION_UMBRELLA 20292 /* Cisco Umbrella temporary assignment */
|
#define EDNS0_OPTION_UMBRELLA 20292 /* Cisco Umbrella temporary assignment */
|
||||||
|
|
||||||
/* RFC-8914 extended errors */
|
/* RFC-8914 extended errors, negative values are our definitions */
|
||||||
|
#define EDE_UNSET -1 /* No extended DNS error available */
|
||||||
#define EDE_OTHER 0 /* Other */
|
#define EDE_OTHER 0 /* Other */
|
||||||
#define EDE_USUPDNSKEY 1 /* Unsupported DNSKEY algo */
|
#define EDE_USUPDNSKEY 1 /* Unsupported DNSKEY algo */
|
||||||
#define EDE_USUPDS 2 /* Unsupported DS Digest */
|
#define EDE_USUPDS 2 /* Unsupported DS Digest */
|
||||||
|
|||||||
+33
-19
@@ -437,8 +437,6 @@ int main (int argc, char **argv)
|
|||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
daemon->dbus = NULL;
|
|
||||||
daemon->watches = NULL;
|
|
||||||
if ((err = dbus_init()))
|
if ((err = dbus_init()))
|
||||||
die(_("DBus error: %s"), err, EC_MISC);
|
die(_("DBus error: %s"), err, EC_MISC);
|
||||||
}
|
}
|
||||||
@@ -450,7 +448,6 @@ int main (int argc, char **argv)
|
|||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
daemon->ubus = NULL;
|
|
||||||
if ((err = ubus_init()))
|
if ((err = ubus_init()))
|
||||||
die(_("UBus error: %s"), err, EC_MISC);
|
die(_("UBus error: %s"), err, EC_MISC);
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1062,8 @@ int main (int argc, char **argv)
|
|||||||
set_dns_listeners();
|
set_dns_listeners();
|
||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
set_dbus_listeners();
|
if (option_bool(OPT_DBUS))
|
||||||
|
set_dbus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
@@ -1192,28 +1190,44 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
/* if we didn't create a DBus connection, retry now. */
|
/* if we didn't create a DBus connection, retry now. */
|
||||||
if (option_bool(OPT_DBUS) && !daemon->dbus)
|
if (option_bool(OPT_DBUS))
|
||||||
{
|
{
|
||||||
char *err;
|
if (!daemon->dbus)
|
||||||
if ((err = dbus_init()))
|
{
|
||||||
my_syslog(LOG_WARNING, _("DBus error: %s"), err);
|
char *err = dbus_init();
|
||||||
if (daemon->dbus)
|
|
||||||
my_syslog(LOG_INFO, _("connected to system DBus"));
|
if (daemon->dbus)
|
||||||
|
my_syslog(LOG_INFO, _("connected to system DBus"));
|
||||||
|
else if (err)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("DBus error: %s"), err);
|
||||||
|
reset_option_bool(OPT_DBUS); /* fatal error, stop trying. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check_dbus_listeners();
|
||||||
}
|
}
|
||||||
check_dbus_listeners();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
/* if we didn't create a UBus connection, retry now. */
|
/* if we didn't create a UBus connection, retry now. */
|
||||||
if (option_bool(OPT_UBUS) && !daemon->ubus)
|
if (option_bool(OPT_UBUS))
|
||||||
{
|
{
|
||||||
char *err;
|
if (!daemon->ubus)
|
||||||
if ((err = ubus_init()))
|
{
|
||||||
my_syslog(LOG_WARNING, _("UBus error: %s"), err);
|
char *err = ubus_init();
|
||||||
if (daemon->ubus)
|
|
||||||
my_syslog(LOG_INFO, _("connected to system UBus"));
|
if (daemon->ubus)
|
||||||
|
my_syslog(LOG_INFO, _("connected to system UBus"));
|
||||||
|
else if (err)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("UBus error: %s"), err);
|
||||||
|
reset_option_bool(OPT_UBUS); /* fatal error, stop trying. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check_ubus_listeners();
|
||||||
}
|
}
|
||||||
check_ubus_listeners();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
check_dns_listeners(now);
|
check_dns_listeners(now);
|
||||||
|
|||||||
+11
-6
@@ -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) )
|
||||||
@@ -329,7 +331,8 @@ union all_addr {
|
|||||||
|
|
||||||
|
|
||||||
struct bogus_addr {
|
struct bogus_addr {
|
||||||
struct in_addr addr, mask;
|
int is6, prefix;
|
||||||
|
union all_addr addr;
|
||||||
struct bogus_addr *next;
|
struct bogus_addr *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -536,8 +539,8 @@ union mysockaddr {
|
|||||||
#define SERV_FOR_NODOTS 32 /* server for names with no domain part only */
|
#define SERV_FOR_NODOTS 32 /* server for names with no domain part only */
|
||||||
#define SERV_WARNED_RECURSIVE 64 /* avoid warning spam */
|
#define SERV_WARNED_RECURSIVE 64 /* avoid warning spam */
|
||||||
#define SERV_FROM_DBUS 128 /* 1 if source is DBus */
|
#define SERV_FROM_DBUS 128 /* 1 if source is DBus */
|
||||||
#define SERV_MARK 256 /* for mark-and-delete */
|
#define SERV_MARK 256 /* for mark-and-delete and log code */
|
||||||
#define SERV_COUNTED 512 /* workspace for log code */
|
#define SERV_WILDCARD 512 /* domain has leading '*' */
|
||||||
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
|
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
|
||||||
#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */
|
#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */
|
||||||
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
||||||
@@ -958,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1103,6 +1106,7 @@ extern struct daemon {
|
|||||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
||||||
struct bogus_addr *bogus_addr, *ignore_addr;
|
struct bogus_addr *bogus_addr, *ignore_addr;
|
||||||
struct server *servers, *local_domains, **serverarray, *no_rebind;
|
struct server *servers, *local_domains, **serverarray, *no_rebind;
|
||||||
|
int server_has_wildcard;
|
||||||
int serverarraysz, serverarrayhwm;
|
int serverarraysz, serverarrayhwm;
|
||||||
struct ipsets *ipsets;
|
struct ipsets *ipsets;
|
||||||
u32 allowlist_mask;
|
u32 allowlist_mask;
|
||||||
@@ -1367,6 +1371,7 @@ int hostname_issubdomain(char *a, char *b);
|
|||||||
time_t dnsmasq_time(void);
|
time_t dnsmasq_time(void);
|
||||||
int netmask_length(struct in_addr mask);
|
int netmask_length(struct in_addr mask);
|
||||||
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||||
|
int is_same_net_prefix(struct in_addr a, struct in_addr b, int prefix);
|
||||||
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
|
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
|
||||||
u64 addr6part(struct in6_addr *addr);
|
u64 addr6part(struct in6_addr *addr);
|
||||||
void setaddr6part(struct in6_addr *addr, u64 host);
|
void setaddr6part(struct in6_addr *addr, u64 host);
|
||||||
|
|||||||
+3
-2
@@ -744,7 +744,8 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return STAT_BOGUS | failflags;
|
/* If we reach this point, no verifying key was found */
|
||||||
|
return STAT_BOGUS | failflags | DNSSEC_FAIL_NOKEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2193,6 +2194,6 @@ int errflags_to_ede(int status)
|
|||||||
else if (status & DNSSEC_FAIL_NOSIG)
|
else if (status & DNSSEC_FAIL_NOSIG)
|
||||||
return EDE_NO_RRSIG;
|
return EDE_NO_RRSIG;
|
||||||
else
|
else
|
||||||
return -1;
|
return EDE_UNSET;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_DNSSEC */
|
#endif /* HAVE_DNSSEC */
|
||||||
+111
-42
@@ -32,10 +32,18 @@ void build_server_array(void)
|
|||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
if (!(serv->flags & SERV_LOOP))
|
if (!(serv->flags & SERV_LOOP))
|
||||||
#endif
|
#endif
|
||||||
count++;
|
{
|
||||||
|
count++;
|
||||||
|
if (serv->flags & SERV_WILDCARD)
|
||||||
|
daemon->server_has_wildcard = 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (serv = daemon->local_domains; serv; serv = serv->next)
|
for (serv = daemon->local_domains; serv; serv = serv->next)
|
||||||
count++;
|
{
|
||||||
|
count++;
|
||||||
|
if (serv->flags & SERV_WILDCARD)
|
||||||
|
daemon->server_has_wildcard = 1;
|
||||||
|
}
|
||||||
|
|
||||||
daemon->serverarraysz = count;
|
daemon->serverarraysz = count;
|
||||||
|
|
||||||
@@ -57,7 +65,7 @@ void build_server_array(void)
|
|||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next, count++)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
if (!(serv->flags & SERV_LOOP))
|
if (!(serv->flags & SERV_LOOP))
|
||||||
#endif
|
#endif
|
||||||
@@ -65,6 +73,7 @@ void build_server_array(void)
|
|||||||
daemon->serverarray[count] = serv;
|
daemon->serverarray[count] = serv;
|
||||||
serv->serial = count;
|
serv->serial = count;
|
||||||
serv->last_server = -1;
|
serv->last_server = -1;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (serv = daemon->local_domains; serv; serv = serv->next, count++)
|
for (serv = daemon->local_domains; serv; serv = serv->next, count++)
|
||||||
@@ -92,13 +101,13 @@ void build_server_array(void)
|
|||||||
reply of IPv4 or IPV6.
|
reply of IPv4 or IPV6.
|
||||||
return 0 if nothing found, 1 otherwise.
|
return 0 if nothing found, 1 otherwise.
|
||||||
*/
|
*/
|
||||||
int lookup_domain(char *qdomain, int flags, int *lowout, int *highout)
|
int lookup_domain(char *domain, int flags, int *lowout, int *highout)
|
||||||
{
|
{
|
||||||
int rc, crop_query, nodots;
|
int rc, crop_query, nodots;
|
||||||
ssize_t qlen;
|
ssize_t qlen;
|
||||||
int try, high, low = 0;
|
int try, high, low = 0;
|
||||||
int nlow = 0, nhigh = 0;
|
int nlow = 0, nhigh = 0;
|
||||||
char *cp;
|
char *cp, *qdomain = domain;
|
||||||
|
|
||||||
/* may be no configured servers. */
|
/* may be no configured servers. */
|
||||||
if (daemon->serverarraysz == 0)
|
if (daemon->serverarraysz == 0)
|
||||||
@@ -178,16 +187,36 @@ int lookup_domain(char *qdomain, int flags, int *lowout, int *highout)
|
|||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
{
|
{
|
||||||
/* We've matched a setting which says to use servers without a domain.
|
int found = 1;
|
||||||
Continue the search with empty query */
|
|
||||||
if (daemon->serverarray[try]->flags & SERV_USE_RESOLV)
|
if (daemon->server_has_wildcard)
|
||||||
crop_query = qlen;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* We have a match, but it may only be (say) an IPv6 address, and
|
/* if we have example.com and *example.com we need to check against *example.com,
|
||||||
if the query wasn't for an AAAA record, it's no good, and we need
|
but the binary search may have found either. Use the fact that example.com is sorted before *example.com
|
||||||
to continue generalising */
|
We favour example.com in the case that both match (ie www.example.com) */
|
||||||
if (filter_servers(try, flags, &nlow, &nhigh))
|
while (try != 0 && order(qdomain, qlen, daemon->serverarray[try-1]) == 0)
|
||||||
|
try--;
|
||||||
|
|
||||||
|
if (!(qdomain == domain || *qdomain == 0 || *(qdomain-1) == '.'))
|
||||||
|
{
|
||||||
|
while (try < daemon->serverarraysz-1 && order(qdomain, qlen, daemon->serverarray[try+1]) == 0)
|
||||||
|
try++;
|
||||||
|
|
||||||
|
if (!(daemon->serverarray[try]->flags & SERV_WILDCARD))
|
||||||
|
found = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
/* We've matched a setting which says to use servers without a domain.
|
||||||
|
Continue the search with empty query */
|
||||||
|
if (daemon->serverarray[try]->flags & SERV_USE_RESOLV)
|
||||||
|
crop_query = qlen;
|
||||||
|
else if (filter_servers(try, flags, &nlow, &nhigh))
|
||||||
|
/* We have a match, but it may only be (say) an IPv6 address, and
|
||||||
|
if the query wasn't for an AAAA record, it's no good, and we need
|
||||||
|
to continue generalising */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,11 +226,13 @@ int lookup_domain(char *qdomain, int flags, int *lowout, int *highout)
|
|||||||
crop_query = 1;
|
crop_query = 1;
|
||||||
|
|
||||||
/* strip chars off the query based on the largest possible remaining match,
|
/* strip chars off the query based on the largest possible remaining match,
|
||||||
then continue to the start of the next label. */
|
then continue to the start of the next label unless we have a wildcard
|
||||||
|
domain somewhere, in which case we have to go one at a time. */
|
||||||
qlen -= crop_query;
|
qlen -= crop_query;
|
||||||
qdomain += crop_query;
|
qdomain += crop_query;
|
||||||
while (qlen > 0 && (*(qdomain-1) != '.'))
|
if (!daemon->server_has_wildcard)
|
||||||
qlen--, qdomain++;
|
while (qlen > 0 && (*(qdomain-1) != '.'))
|
||||||
|
qlen--, qdomain++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* domain has no dots, and we have at least one server configured to handle such,
|
/* domain has no dots, and we have at least one server configured to handle such,
|
||||||
@@ -212,11 +243,6 @@ int lookup_domain(char *qdomain, int flags, int *lowout, int *highout)
|
|||||||
(nlow == nhigh || daemon->serverarray[nlow]->domain_len == 0))
|
(nlow == nhigh || daemon->serverarray[nlow]->domain_len == 0))
|
||||||
filter_servers(daemon->serverarraysz-1, flags, &nlow, &nhigh);
|
filter_servers(daemon->serverarraysz-1, flags, &nlow, &nhigh);
|
||||||
|
|
||||||
/* F_DOMAINSRV returns only domain-specific servers, so if we got to a
|
|
||||||
general server, return empty set. */
|
|
||||||
if (nlow != nhigh && (flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0)
|
|
||||||
nlow = nhigh;
|
|
||||||
|
|
||||||
if (lowout)
|
if (lowout)
|
||||||
*lowout = nlow;
|
*lowout = nlow;
|
||||||
|
|
||||||
@@ -251,19 +277,26 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
|||||||
|
|
||||||
nhigh++;
|
nhigh++;
|
||||||
|
|
||||||
/* Now the servers are on order between low and high, in the order
|
|
||||||
return zero for both, IPv6 addr, IPv4 addr, no-data return, send upstream.
|
|
||||||
|
|
||||||
See which of those match our query in that priority order and narrow (low, high) */
|
|
||||||
|
|
||||||
#define SERV_LOCAL_ADDRESS (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)
|
#define SERV_LOCAL_ADDRESS (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)
|
||||||
|
|
||||||
for (i = nlow; (flags & F_CONFIG) && i < nhigh && (daemon->serverarray[i]->flags & SERV_LOCAL_ADDRESS); i++);
|
if (flags & F_CONFIG)
|
||||||
|
{
|
||||||
|
/* We're just lookin for any matches that return an RR. */
|
||||||
|
for (i = nlow; i < nhigh; i++)
|
||||||
|
if (daemon->serverarray[i]->flags & SERV_LOCAL_ADDRESS)
|
||||||
|
break;
|
||||||
|
|
||||||
if (i != nlow)
|
/* failed, return failure. */
|
||||||
nhigh = i;
|
if (i == nhigh)
|
||||||
|
nhigh = nlow;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Now the servers are on order between low and high, in the order
|
||||||
|
IPv6 addr, IPv4 addr, return zero for both, send upstream, no-data return.
|
||||||
|
|
||||||
|
See which of those match our query in that priority order and narrow (low, high) */
|
||||||
|
|
||||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_6ADDR); i++);
|
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_6ADDR); i++);
|
||||||
|
|
||||||
if (i != nlow && (flags & F_IPV6))
|
if (i != nlow && (flags & F_IPV6))
|
||||||
@@ -288,18 +321,26 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
|||||||
{
|
{
|
||||||
nlow = i;
|
nlow = i;
|
||||||
|
|
||||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
|
/* now look for a server */
|
||||||
|
for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
|
||||||
|
|
||||||
/* --local=/domain/, only return if we don't need a server. */
|
if (i != nlow)
|
||||||
if (i != nlow && !(flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER)))
|
|
||||||
nhigh = i;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
nlow = i;
|
|
||||||
/* If we want a server that can do DNSSEC, and this one can't,
|
/* If we want a server that can do DNSSEC, and this one can't,
|
||||||
return nothing. */
|
return nothing, similarly if were looking only for a server
|
||||||
|
for a particular domain. */
|
||||||
if ((flags & F_DNSSECOK) && !(daemon->serverarray[nlow]->flags & SERV_DO_DNSSEC))
|
if ((flags & F_DNSSECOK) && !(daemon->serverarray[nlow]->flags & SERV_DO_DNSSEC))
|
||||||
nlow = nhigh;
|
nlow = nhigh;
|
||||||
|
else if ((flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0)
|
||||||
|
nlow = nhigh;
|
||||||
|
else
|
||||||
|
nhigh = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* --local=/domain/, only return if we don't need a server. */
|
||||||
|
if (flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER))
|
||||||
|
nhigh = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,13 +490,22 @@ static int order(char *qdomain, size_t qlen, struct server *serv)
|
|||||||
|
|
||||||
static int order_servers(struct server *s1, struct server *s2)
|
static int order_servers(struct server *s1, struct server *s2)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* need full comparison of dotless servers in
|
/* need full comparison of dotless servers in
|
||||||
order_qsort() and filter_servers() */
|
order_qsort() and filter_servers() */
|
||||||
|
|
||||||
if (s1->flags & SERV_FOR_NODOTS)
|
if (s1->flags & SERV_FOR_NODOTS)
|
||||||
return (s2->flags & SERV_FOR_NODOTS) ? 0 : 1;
|
return (s2->flags & SERV_FOR_NODOTS) ? 0 : 1;
|
||||||
|
|
||||||
return order(s1->domain, s1->domain_len, s2);
|
if ((rc = order(s1->domain, s1->domain_len, s2)) != 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* For identical domains, sort wildcard ones first */
|
||||||
|
if (s1->flags & SERV_WILDCARD)
|
||||||
|
return (s2->flags & SERV_WILDCARD) ? 0 : 1;
|
||||||
|
|
||||||
|
return (s2->flags & SERV_WILDCARD) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int order_qsort(const void *a, const void *b)
|
static int order_qsort(const void *a, const void *b)
|
||||||
@@ -468,10 +518,12 @@ static int order_qsort(const void *a, const void *b)
|
|||||||
rc = order_servers(s1, s2);
|
rc = order_servers(s1, s2);
|
||||||
|
|
||||||
/* Sort all literal NODATA and local IPV4 or IPV6 responses together,
|
/* Sort all literal NODATA and local IPV4 or IPV6 responses together,
|
||||||
in a very specific order. */
|
in a very specific order. We flip the SERV_LITERAL_ADDRESS bit
|
||||||
|
so the order is IPv6 literal, IPv4 literal, all-zero literal,
|
||||||
|
upstream server, NXDOMAIN literal. */
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = (s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) -
|
rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) -
|
||||||
(s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS));
|
((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS);
|
||||||
|
|
||||||
/* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */
|
/* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
@@ -489,10 +541,14 @@ void mark_servers(int flag)
|
|||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
if (serv->flags & flag)
|
if (serv->flags & flag)
|
||||||
serv->flags |= SERV_MARK;
|
serv->flags |= SERV_MARK;
|
||||||
|
else
|
||||||
|
serv->flags &= ~SERV_MARK;
|
||||||
|
|
||||||
for (serv = daemon->local_domains; serv; serv = serv->next)
|
for (serv = daemon->local_domains; serv; serv = serv->next)
|
||||||
if (serv->flags & flag)
|
if (serv->flags & flag)
|
||||||
serv->flags |= SERV_MARK;
|
serv->flags |= SERV_MARK;
|
||||||
|
else
|
||||||
|
serv->flags &= ~SERV_MARK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_servers(void)
|
void cleanup_servers(void)
|
||||||
@@ -538,7 +594,20 @@ int add_update_server(int flags,
|
|||||||
struct server *serv = NULL;
|
struct server *serv = NULL;
|
||||||
char *alloc_domain;
|
char *alloc_domain;
|
||||||
|
|
||||||
if (!domain || strlen(domain) == 0)
|
if (!domain)
|
||||||
|
domain = "";
|
||||||
|
|
||||||
|
/* .domain == domain, for historical reasons. */
|
||||||
|
if (*domain == '.')
|
||||||
|
while (*domain == '.') domain++;
|
||||||
|
else if (*domain == '*')
|
||||||
|
{
|
||||||
|
domain++;
|
||||||
|
if (*domain != 0)
|
||||||
|
flags |= SERV_WILDCARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*domain == 0)
|
||||||
alloc_domain = whine_malloc(1);
|
alloc_domain = whine_malloc(1);
|
||||||
else if (!(alloc_domain = canonicalise((char *)domain, NULL)))
|
else if (!(alloc_domain = canonicalise((char *)domain, NULL)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+34
-30
@@ -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,26 +136,7 @@ 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 */
|
||||||
@@ -246,12 +228,20 @@ 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;
|
||||||
|
|||||||
+26
-13
@@ -177,7 +177,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
int subnet, cacheable, forwarded = 0;
|
int subnet, cacheable, forwarded = 0;
|
||||||
size_t edns0_len;
|
size_t edns0_len;
|
||||||
unsigned char *pheader;
|
unsigned char *pheader;
|
||||||
int ede = -1;
|
int ede = EDE_UNSET;
|
||||||
(void)do_bit;
|
(void)do_bit;
|
||||||
|
|
||||||
if (header->hb4 & HB4_CD)
|
if (header->hb4 & HB4_CD)
|
||||||
@@ -537,7 +537,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
{
|
{
|
||||||
u16 swap = htons((u16)ede);
|
u16 swap = htons((u16)ede);
|
||||||
|
|
||||||
if (ede != -1)
|
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);
|
||||||
@@ -734,12 +734,6 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pheader && ede != -1)
|
|
||||||
{
|
|
||||||
u16 swap = htons((u16)ede);
|
|
||||||
n = add_pseudoheader(header, n, limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do this after extract_addresses. Ensure NODATA reply and remove
|
/* do this after extract_addresses. Ensure NODATA reply and remove
|
||||||
nameserver info. */
|
nameserver info. */
|
||||||
if (munged)
|
if (munged)
|
||||||
@@ -753,7 +747,15 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
/* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
|
/* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
|
||||||
sections of the packet. Find the new length here and put back pseudoheader
|
sections of the packet. Find the new length here and put back pseudoheader
|
||||||
if it was removed. */
|
if it was removed. */
|
||||||
return resize_packet(header, n, pheader, plen);
|
n = resize_packet(header, n, pheader, plen);
|
||||||
|
|
||||||
|
if (pheader && ede != EDE_UNSET)
|
||||||
|
{
|
||||||
|
u16 swap = htons((u16)ede);
|
||||||
|
n = add_pseudoheader(header, n, limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
@@ -1092,7 +1094,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
|
|||||||
{
|
{
|
||||||
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
|
int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
|
||||||
size_t nn;
|
size_t nn;
|
||||||
int ede = -1;
|
int ede = EDE_UNSET;
|
||||||
|
|
||||||
(void)status;
|
(void)status;
|
||||||
|
|
||||||
@@ -1240,6 +1242,8 @@ static int is_query_allowed_for_mark(u32 mark, const char *name)
|
|||||||
static size_t answer_disallowed(struct dns_header *header, size_t qlen, u32 mark, const char *name)
|
static size_t answer_disallowed(struct dns_header *header, size_t qlen, u32 mark, const char *name)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
(void)name;
|
||||||
|
(void)mark;
|
||||||
|
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
if (name)
|
if (name)
|
||||||
@@ -1580,6 +1584,9 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
|
|
||||||
if (m >= 1)
|
if (m >= 1)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr);
|
||||||
|
#endif
|
||||||
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||||
(char *)header, m, &source_addr, &dst_addr, if_index);
|
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||||
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
||||||
@@ -1593,6 +1600,9 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
local_auth, do_bit, have_pseudoheader);
|
local_auth, do_bit, have_pseudoheader);
|
||||||
if (m >= 1)
|
if (m >= 1)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr);
|
||||||
|
#endif
|
||||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||||
if (local_auth)
|
if (local_auth)
|
||||||
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
|
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
|
||||||
@@ -1607,7 +1617,7 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ad_reqd = do_bit;
|
int ad_reqd = do_bit;
|
||||||
/* RFC 6840 5.7 */
|
/* RFC 6840 5.7 */
|
||||||
if (header->hb4 & HB4_AD)
|
if (header->hb4 & HB4_AD)
|
||||||
ad_reqd = 1;
|
ad_reqd = 1;
|
||||||
|
|
||||||
@@ -1616,6 +1626,9 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
|
|
||||||
if (m >= 1)
|
if (m >= 1)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr);
|
||||||
|
#endif
|
||||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||||
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
|
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
|
||||||
report_addresses(header, m, mark);
|
report_addresses(header, m, mark);
|
||||||
@@ -1905,7 +1918,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int ede = -1;
|
int ede = EDE_UNSET;
|
||||||
|
|
||||||
if (query_count == TCP_MAX_QUERIES ||
|
if (query_count == TCP_MAX_QUERIES ||
|
||||||
!packet ||
|
!packet ||
|
||||||
@@ -2136,7 +2149,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
{
|
{
|
||||||
u16 swap = htons((u16)ede);
|
u16 swap = htons((u16)ede);
|
||||||
|
|
||||||
if (ede != -1)
|
if (ede != EDE_UNSET)
|
||||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
|
||||||
else
|
else
|
||||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||||
|
|||||||
@@ -236,7 +236,6 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
/* stringify MAC into dhcp_buff */
|
/* stringify MAC into dhcp_buff */
|
||||||
p = daemon->dhcp_buff;
|
p = daemon->dhcp_buff;
|
||||||
if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0)
|
if (data.hwaddr_type != ARPHRD_ETHER || data.hwaddr_len == 0)
|
||||||
|
|||||||
@@ -1021,6 +1021,7 @@ void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
kill_name(lease_tmp);
|
kill_name(lease_tmp);
|
||||||
|
lease_tmp->flags |= LEASE_CHANGED; /* run script on change */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -1507,6 +1507,9 @@ void check_servers(int no_loop_check)
|
|||||||
loop_send_probes();
|
loop_send_probes();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* clear all marks. */
|
||||||
|
mark_servers(0);
|
||||||
|
|
||||||
/* interface may be new since startup */
|
/* interface may be new since startup */
|
||||||
if (!option_bool(OPT_NOWILD))
|
if (!option_bool(OPT_NOWILD))
|
||||||
enumerate_interfaces(0);
|
enumerate_interfaces(0);
|
||||||
@@ -1588,7 +1591,7 @@ void check_servers(int no_loop_check)
|
|||||||
|
|
||||||
if (strlen(serv->domain) != 0 || (serv->flags & SERV_FOR_NODOTS))
|
if (strlen(serv->domain) != 0 || (serv->flags & SERV_FOR_NODOTS))
|
||||||
{
|
{
|
||||||
char *s1, *s2, *s3 = "";
|
char *s1, *s2, *s3 = "", *s4 = "";
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
|
if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
|
||||||
@@ -1599,9 +1602,9 @@ void check_servers(int no_loop_check)
|
|||||||
else if (strlen(serv->domain) == 0)
|
else if (strlen(serv->domain) == 0)
|
||||||
s1 = _("default"), s2 = "";
|
s1 = _("default"), s2 = "";
|
||||||
else
|
else
|
||||||
s1 = _("domain"), s2 = serv->domain;
|
s1 = _("domain"), s2 = serv->domain, s4 = (serv->flags & SERV_WILDCARD) ? "*" : "";
|
||||||
|
|
||||||
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
|
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s%s %s"), daemon->namebuff, port, s1, s4, s2, s3);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
else if (serv->flags & SERV_LOOP)
|
else if (serv->flags & SERV_LOOP)
|
||||||
|
|||||||
+73
-40
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -2527,30 +2547,47 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case 'B': /* --bogus-nxdomain */
|
case 'B': /* --bogus-nxdomain */
|
||||||
case LOPT_IGNORE_ADDR: /* --ignore-address */
|
case LOPT_IGNORE_ADDR: /* --ignore-address */
|
||||||
{
|
{
|
||||||
struct in_addr addr;
|
union all_addr addr;
|
||||||
int prefix = 32;
|
int prefix, is6 = 0;
|
||||||
|
struct bogus_addr *baddr;
|
||||||
|
|
||||||
unhide_metas(arg);
|
unhide_metas(arg);
|
||||||
|
|
||||||
if (!arg ||
|
if (!arg ||
|
||||||
((comma = split_chr(arg, '/')) && !atoi_check(comma, &prefix)) ||
|
((comma = split_chr(arg, '/')) && !atoi_check(comma, &prefix)))
|
||||||
(inet_pton(AF_INET, arg, &addr) != 1))
|
ret_err(gen_err);
|
||||||
ret_err(gen_err); /* error */
|
|
||||||
|
if (inet_pton(AF_INET6, arg, &addr.addr6) == 1)
|
||||||
|
is6 = 1;
|
||||||
|
else if (inet_pton(AF_INET, arg, &addr.addr4) != 1)
|
||||||
|
ret_err(gen_err);
|
||||||
|
|
||||||
|
if (!comma)
|
||||||
|
{
|
||||||
|
if (is6)
|
||||||
|
prefix = 128;
|
||||||
|
else
|
||||||
|
prefix = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix > 128 || (!is6 && prefix > 32))
|
||||||
|
ret_err(gen_err);
|
||||||
|
|
||||||
|
baddr = opt_malloc(sizeof(struct bogus_addr));
|
||||||
|
if (option == 'B')
|
||||||
|
{
|
||||||
|
baddr->next = daemon->bogus_addr;
|
||||||
|
daemon->bogus_addr = baddr;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
|
baddr->next = daemon->ignore_addr;
|
||||||
if (option == 'B')
|
daemon->ignore_addr = baddr;
|
||||||
{
|
|
||||||
baddr->next = daemon->bogus_addr;
|
|
||||||
daemon->bogus_addr = baddr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
baddr->next = daemon->ignore_addr;
|
|
||||||
daemon->ignore_addr = baddr;
|
|
||||||
}
|
|
||||||
baddr->mask.s_addr = htonl(~((1 << (32 - prefix)) - 1));
|
|
||||||
baddr->addr.s_addr = addr.s_addr & baddr->mask.s_addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
baddr->prefix = prefix;
|
||||||
|
baddr->is6 = is6;
|
||||||
|
baddr->addr = addr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2636,11 +2673,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
char *last;
|
char *last;
|
||||||
|
|
||||||
arg++;
|
domain = lastdomain = ++arg;
|
||||||
/* elide leading dots - they are implied in the search algorithm */
|
|
||||||
while (*arg == '.') arg++;
|
|
||||||
|
|
||||||
domain = lastdomain = arg;
|
|
||||||
|
|
||||||
while ((last = split_chr(arg, '/')))
|
while ((last = split_chr(arg, '/')))
|
||||||
{
|
{
|
||||||
@@ -4150,13 +4183,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;
|
||||||
|
|||||||
+44
-37
@@ -364,7 +364,7 @@ int private_net(struct in_addr addr, int ban_localhost)
|
|||||||
|
|
||||||
return
|
return
|
||||||
(((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ ||
|
(((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost) /* 127.0.0.0/8 (loopback) */ ||
|
||||||
((ip_addr & 0xFF000000) == 0x00000000) /* RFC 5735 section 3. "here" network */ ||
|
(((ip_addr & 0xFF000000) == 0x00000000) && ban_localhost) /* RFC 5735 section 3. "here" network */ ||
|
||||||
((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
|
((ip_addr & 0xFF000000) == 0x0A000000) /* 10.0.0.0/8 (private) */ ||
|
||||||
((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
|
((ip_addr & 0xFFF00000) == 0xAC100000) /* 172.16.0.0/12 (private) */ ||
|
||||||
((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
|
((ip_addr & 0xFFFF0000) == 0xC0A80000) /* 192.168.0.0/16 (private) */ ||
|
||||||
@@ -375,12 +375,21 @@ int private_net(struct in_addr addr, int ban_localhost)
|
|||||||
((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF) /* 255.255.255.255/32 (broadcast)*/ ;
|
((ip_addr & 0xFFFFFFFF) == 0xFFFFFFFF) /* 255.255.255.255/32 (broadcast)*/ ;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int private_net6(struct in6_addr *a)
|
static int private_net6(struct in6_addr *a, int ban_localhost)
|
||||||
{
|
{
|
||||||
|
/* Block IPv4-mapped IPv6 addresses in private IPv4 address space */
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(a))
|
||||||
|
{
|
||||||
|
struct in_addr v4;
|
||||||
|
v4.s_addr = ((const uint32_t *) (a))[3];
|
||||||
|
return private_net(v4, ban_localhost);
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
IN6_IS_ADDR_UNSPECIFIED(a) || /* RFC 6303 4.3 */
|
(IN6_IS_ADDR_UNSPECIFIED(a) && ban_localhost) || /* RFC 6303 4.3 */
|
||||||
IN6_IS_ADDR_LOOPBACK(a) || /* RFC 6303 4.3 */
|
(IN6_IS_ADDR_LOOPBACK(a) && ban_localhost) || /* RFC 6303 4.3 */
|
||||||
IN6_IS_ADDR_LINKLOCAL(a) || /* RFC 6303 4.5 */
|
IN6_IS_ADDR_LINKLOCAL(a) || /* RFC 6303 4.5 */
|
||||||
|
IN6_IS_ADDR_SITELOCAL(a) ||
|
||||||
((unsigned char *)a)[0] == 0xfd || /* RFC 6303 4.4 */
|
((unsigned char *)a)[0] == 0xfd || /* RFC 6303 4.4 */
|
||||||
((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */
|
((u32 *)a)[0] == htonl(0x20010db8); /* RFC 6303 4.6 */
|
||||||
}
|
}
|
||||||
@@ -795,28 +804,9 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
private_net(addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
private_net(addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Block IPv4-mapped IPv6 addresses in private IPv4 address space */
|
if ((flags & F_IPV6) &&
|
||||||
if (flags & F_IPV6)
|
private_net6(&addr.addr6, !option_bool(OPT_LOCAL_REBIND)))
|
||||||
{
|
return 1;
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&addr.addr6))
|
|
||||||
{
|
|
||||||
struct in_addr v4;
|
|
||||||
v4.s_addr = ((const uint32_t *) (&addr.addr6))[3];
|
|
||||||
if (private_net(v4, !option_bool(OPT_LOCAL_REBIND)))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for link-local (LL) and site-local (ULA) IPv6 addresses */
|
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&addr.addr6) ||
|
|
||||||
IN6_IS_ADDR_SITELOCAL(&addr.addr6))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Check for the IPv6 loopback address (::1) when
|
|
||||||
option rebind-localhost-ok is NOT set */
|
|
||||||
if (!option_bool(OPT_LOCAL_REBIND) &&
|
|
||||||
IN6_IS_ADDR_LOOPBACK(&addr.addr6))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPSET
|
#ifdef HAVE_IPSET
|
||||||
@@ -982,10 +972,12 @@ unsigned int extract_request(struct dns_header *header, size_t qlen, char *name,
|
|||||||
|
|
||||||
*name = 0; /* return empty name if no query found. */
|
*name = 0; /* return empty name if no query found. */
|
||||||
|
|
||||||
if (ntohs(header->qdcount) != 1 || OPCODE(header) != QUERY ||
|
if (ntohs(header->qdcount) != 1 || OPCODE(header) != QUERY)
|
||||||
ntohs(header->ancount) != 0 || ntohs(header->nscount) != 0)
|
|
||||||
return 0; /* must be exactly one query. */
|
return 0; /* must be exactly one query. */
|
||||||
|
|
||||||
|
if (!(header->hb3 & HB3_QR) && (ntohs(header->ancount) != 0 || ntohs(header->nscount) != 0))
|
||||||
|
return 0; /* non-standard query. */
|
||||||
|
|
||||||
if (!extract_name(header, qlen, &p, name, 1, 4))
|
if (!extract_name(header, qlen, &p, name, 1, 4))
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
|
|
||||||
@@ -1087,7 +1079,6 @@ static int check_bad_address(struct dns_header *header, size_t qlen, struct bogu
|
|||||||
int i, qtype, qclass, rdlen;
|
int i, qtype, qclass, rdlen;
|
||||||
unsigned long ttl;
|
unsigned long ttl;
|
||||||
struct bogus_addr *baddrp;
|
struct bogus_addr *baddrp;
|
||||||
struct in_addr addr;
|
|
||||||
|
|
||||||
/* skip over questions */
|
/* skip over questions */
|
||||||
if (!(p = skip_questions(header, qlen)))
|
if (!(p = skip_questions(header, qlen)))
|
||||||
@@ -1109,17 +1100,33 @@ static int check_bad_address(struct dns_header *header, size_t qlen, struct bogu
|
|||||||
if (ttlp)
|
if (ttlp)
|
||||||
*ttlp = ttl;
|
*ttlp = ttl;
|
||||||
|
|
||||||
if (qclass == C_IN && qtype == T_A)
|
if (qclass == C_IN)
|
||||||
{
|
{
|
||||||
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
|
if (qtype == T_A)
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
|
|
||||||
{
|
{
|
||||||
|
struct in_addr addr;
|
||||||
|
|
||||||
|
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
memcpy(&addr, p, INADDRSZ);
|
memcpy(&addr, p, INADDRSZ);
|
||||||
|
|
||||||
if ((addr.s_addr & baddrp->mask.s_addr) == baddrp->addr.s_addr)
|
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
|
||||||
return 1;
|
if (!baddrp->is6 && is_same_net_prefix(addr, baddrp->addr.addr4, baddrp->prefix))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (qtype == T_AAAA)
|
||||||
|
{
|
||||||
|
struct in6_addr addr;
|
||||||
|
|
||||||
|
if (!CHECK_LEN(header, p, qlen, IN6ADDRSZ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(&addr, p, IN6ADDRSZ);
|
||||||
|
|
||||||
|
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
|
||||||
|
if (baddrp->is6 && is_same_net6(&addr, &baddrp->addr.addr6, baddrp->prefix))
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1618,7 +1625,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (option_bool(OPT_BOGUSPRIV) &&
|
else if (option_bool(OPT_BOGUSPRIV) &&
|
||||||
((is_arpa == F_IPV6 && private_net6(&addr.addr6)) || (is_arpa == F_IPV4 && private_net(addr.addr4, 1))) &&
|
((is_arpa == F_IPV6 && private_net6(&addr.addr6, 1)) || (is_arpa == F_IPV4 && private_net(addr.addr4, 1))) &&
|
||||||
!lookup_domain(name, F_DOMAINSRV, NULL, NULL))
|
!lookup_domain(name, F_DOMAINSRV, NULL, NULL))
|
||||||
{
|
{
|
||||||
/* if no configured server, not in cache, enabled and private IPV4 address, return NXDOMAIN */
|
/* if no configured server, not in cache, enabled and private IPV4 address, return NXDOMAIN */
|
||||||
|
|||||||
+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;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -438,6 +438,16 @@ int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
|||||||
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_same_net_prefix(struct in_addr a, struct in_addr b, int prefix)
|
||||||
|
{
|
||||||
|
struct in_addr mask;
|
||||||
|
|
||||||
|
mask.s_addr = htonl(~((1 << (32 - prefix)) - 1));
|
||||||
|
|
||||||
|
return is_same_net(a, b, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
|
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
|
||||||
{
|
{
|
||||||
int pfbytes = prefixlen >> 3;
|
int pfbytes = prefixlen >> 3;
|
||||||
|
|||||||
Reference in new issue
Block a user