Compare commits

..
20 Commits
Author SHA1 Message Date
Simon Kelley da8b6517de Implement --address=/example.com/#
as (more efficient) syntactic sugar for --address=/example.com/0.0.0.0 and --address=/example.com/::
2018-09-03 23:18:36 +01:00
Simon Kelley c5db8f93ec Tidy 7f876b64c22b2b18412e2e3d8506ee33e42db7c 2018-08-23 23:06:00 +01:00
Simon Kelley 974a6d087a Add --caa-record 2018-08-23 23:01:16 +01:00
Simon Kelley b758b67c37 Improve logging of RRs from --dns-rr. 2018-08-23 21:41:23 +01:00
Simon Kelley 9bafdc62b7 Tidy up file parsing code. 2018-08-21 22:53:38 +01:00
Simon Kelley 97f876b64c Properly deal with unaligned addresses in DHCPv6 packets.
Thanks to Vladislav Grishenko for spotting this.
2018-08-21 22:06:36 +01:00
Simon Kelley cbfbd173c4 Fix broken DNSSEC records in previous. 2018-08-21 18:25:18 +01:00
Simon Kelley b6f926fbef Don't return NXDOMAIN to empty non-terminals.
When a record is defined locally, eg an A record for one.two.example then
we already know that if we forward, eg an AAAA query for one.two.example,
and get back NXDOMAIN, then we need to alter that to NODATA. This is handled
by  check_for_local_domain(). But, if we forward two.example, because
one.two.example exists, then the answer to two.example should also be
a NODATA.

For most local records this is easy, just to substring matching.
for A, AAAA and CNAME records that are in the cache, it's more difficult.
The cache has no efficient way to find such records. The fix is to
insert empty (none of F_IPV4, F_IPV6 F_CNAME set) records for each
non-terminal.

The same considerations apply in auth mode, and the same basic mechanism
is used there too.
2018-08-21 17:46:52 +01:00
Simon Kelley c822620967 Add --dhcp-name-match 2018-08-08 23:46:03 +01:00
Simon Kelley 397c0502e2 Handle case of --auth-zone but no --auth-server. 2018-08-04 21:04:59 +01:00
Simon Kelley 1682d15a74 Add missing EDNS0 section.
EDNS0 section missing in replies to EDNS0-containing queries where
answer generated from --local=/<domain>/
2018-08-03 20:38:18 +01:00
Simon Kelley dd33e98da0 Fix crash parsing a --synth-domain with no prefix.
Problem introduced in 2.79/6b2b564ac34cb3c862f168e6b1457f9f0b9ca69c
2018-07-30 14:55:39 +01:00
Simon Kelley c16d966ad3 Add copyright to src/metrics.h 2018-07-29 22:31:02 +01:00
Simon Kelley 1dfed16071 Remove C99 only code. 2018-07-29 22:16:41 +01:00
Simon Kelley 6f835ed6c8 Format fixes - ubus.c 2018-07-29 22:15:36 +01:00
Kevin Darbyshire-Bryant 9d6fd1727e dnsmasq.c fix OPT_UBUS option usage
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
2018-07-29 22:11:12 +01:00
Simon Kelley 8c1b6a5fd7 New metrics and ubus files. 2018-07-21 22:12:32 +01:00
Julian Kornberger 8dcdb33be9 Add --enable-ubus option. 2018-07-21 22:11:08 +01:00
Julian Kornberger aba8bbb6e3 Add collection of metrics
Data can be retreived via D-Bus und U-Bus
2018-07-21 21:55:08 +01:00
Julian Kornberger caf4d571e6 Add OpenWRT ubus patch
Originally written by John Crispin <john@phrozen.org>
2018-07-21 21:45:03 +01:00
22 changed files with 760 additions and 139 deletions

No files matched your search

+18 -1
View File
@@ -41,8 +41,25 @@ version 2.80
Fix missing fatal errors with some malformed options
(server, local, address, rebind-domain-ok, ipset, alias).
Thanks to Eugene Lozovoy for spotting the problem.
Fix crash on startup with a --synth-domain which has no prefix.
Introduced in 2.79. Thanks to Andreas Engel for the bug report.
Fix missing EDNS0 section in some replies generated by local
DNS configuration which confused systemd-resolvd. Thanks to
Steve Dodd for characterising the problem.
Add --dhcp-name-match config option.
Add --caa-record config option.
Implement --address=/example.com/# as (more efficient) syntactic
sugar for --address=/example.com/0.0.0.0 and
--address=/example.com/::
Returning null addresses is a useful technique for ad-blocking.
Thanks to Peter Russell for the suggestion.
version 2.79
Fix parsing of CNAME arguments, which are confused by extra spaces.
Thanks to Diego Aguirre for spotting the bug.
+4 -3
View File
@@ -53,6 +53,7 @@ top?=$(CURDIR)
dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS $(PKG_CONFIG) --copy -lubox -lubus`
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
@@ -76,16 +77,16 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o metrics.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
all : $(BUILDDIR)
@cd $(BUILDDIR) && $(MAKE) \
top="$(top)" \
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
-f $(top)/Makefile dnsmasq
mostly_clean :
+1 -1
View File
@@ -11,7 +11,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
radv.c slaac.c auth.c ipset.c domain.c \
dnssec.c dnssec-openssl.c blockdata.c tables.c \
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
crypto.c dump.c
crypto.c dump.c ubus.c
LOCAL_MODULE := dnsmasq
+4
View File
@@ -243,6 +243,10 @@ IPv4 or IPv6 address of the lease to remove.
Note that this function will trigger the DhcpLeaseRemoved signal and the
configured DHCP lease script will be run with the "del" action.
GetMetrics
----------
Returns an array with various metrics for DNS and DHCP.
2. SIGNALS
+19 -3
View File
@@ -366,6 +366,11 @@ been built with DBus support. If the service name is given, dnsmasq
provides service at that name, rather than the default which is
.B uk.org.thekelleys.dnsmasq
.TP
.B --enable-ubus
Enable dnsmasq UBus interface. It sends notifications via UBus on
DHCPACK and DHCPRELEASE events. Furthermore it offers metrics.
Requires that dnsmasq has been built with UBus support.
.TP
.B \-o, --strict-order
By default, dnsmasq will send queries to any of the upstream servers
it knows about and tries to favour servers that are known to
@@ -505,7 +510,12 @@ upstream nameserver by a more specific \fB--server\fP directive. As for
\fB--server\fP, one or more domains with no address returns a
no-such-domain answer, so \fB--address=/example.com/\fP is equivalent to
\fB--server=/example.com/\fP and returns NXDOMAIN for example.com and
all its subdomains.
all its subdomains. An address specified as '#' translates to the NULL
address of 0.0.0.0 and its IPv6 equivalent of :: so
\fB--address=/example.com/#\fP will return NULL addresses for example.com and
its subdomains. This is partly syntactic sugar for \fB--address=/example.com/0.0.0.0\fP
and \fB--address=/example.com/::\fP but is also more efficient than including both
as seperate configuration lines.
.TP
.B --ipset=/<domain>[/<domain>...]/<ipset>[,<ipset>...]
Places the resolved IP addresses of queries for one or more domains in
@@ -588,6 +598,9 @@ Return a PTR DNS record.
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
Return an NAPTR DNS record, as specified in RFC3403.
.TP
.B --caa-record=<name>,<flags>,<tag>,<value>
Return a CAA DNS record, as specified in RFC6844.
.TP
.B --cname=<cname>,[<cname>,]<target>[,<TTL>]
Return a CNAME record which indicates that <cname> is really
<target>. There are significant limitations on the target; it must be a
@@ -1324,6 +1337,9 @@ The special form with vi-encap:<enterprise number> matches against
vendor-identifying vendor classes for the specified enterprise. Please
see RFC 3925 for more details of these rare and interesting beasts.
.TP
.B --dhcp-name-match=set:<tag>,<name>[*]
Set the tag if the given name is supplied by a dhcp client. There may be a single trailing wildcard *, which has the usual meaning. Combined with dhcp-ignore or dhcp-ignore-names this gives the ability to ignore certain clients by name, or disallow certain hostnames from being claimed by a client.
.TP
.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
@@ -2254,8 +2270,8 @@ secondary servers for reverse lookups.
When dnsmasq is configured to act as an authoritative server, the
following data is used to populate the authoritative zone.
.PP
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record
, as long as the record names are in the authoritative domain.
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record, --caa-record,
as long as the record names are in the authoritative domain.
.PP
.B --cname
as long as the record name is in the authoritative domain. If the
+16 -14
View File
@@ -103,7 +103,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
char *name = daemon->namebuff;
unsigned char *p, *ansp;
int qtype, qclass;
int qtype, qclass, rc;
int nameoffset, axfroffset = 0;
int q, anscount = 0, authcount = 0;
struct crec *crecp;
@@ -283,11 +283,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (rec = daemon->mxnames; rec; rec = rec->next)
if (!rec->issrv && hostname_isequal(name, rec->name))
if (!rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
{
nxdomain = 0;
if (qtype == T_MX)
if (rc == 2 && qtype == T_MX)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
@@ -298,11 +298,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
if (rec->issrv && hostname_isequal(name, rec->name))
if (rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
{
nxdomain = 0;
if (qtype == T_SRV)
if (rc == 2 && qtype == T_SRV)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
@@ -333,13 +333,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (txt = daemon->rr; txt; txt = txt->next)
if (hostname_isequal(name, txt->name))
if ((rc = hostname_issubdomain(name, txt->name)))
{
nxdomain = 0;
if (txt->class == qtype)
if (rc == 2 && txt->class == qtype)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, txt->class));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
anscount++;
@@ -347,10 +347,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (txt = daemon->txt; txt; txt = txt->next)
if (txt->class == C_IN && hostname_isequal(name, txt->name))
if (txt->class == C_IN && (rc = hostname_issubdomain(name, txt->name)))
{
nxdomain = 0;
if (qtype == T_TXT)
if (rc == 2 && qtype == T_TXT)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
@@ -361,10 +361,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
for (na = daemon->naptr; na; na = na->next)
if (hostname_isequal(name, na->name))
if ((rc = hostname_issubdomain(name, na->name)))
{
nxdomain = 0;
if (qtype == T_NAPTR)
if (rc == 2 && qtype == T_NAPTR)
{
found = 1;
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
@@ -384,13 +384,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
#endif
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
if ((rc = hostname_issubdomain(name, intr->name)))
{
struct addrlist *addrlist;
nxdomain = 0;
if (flag)
if (rc == 2 && flag)
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
(local_query || filter_zone(zone, flag, &addrlist->addr)))
@@ -567,6 +567,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
goto cname_restart;
}
else if (cache_find_non_terminal(name, now))
nxdomain = 0;
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
}
+151 -21
View File
@@ -21,10 +21,12 @@ static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
static struct crec *dhcp_spare = NULL;
#endif
static struct crec *new_chain = NULL;
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
static int insert_error;
static union bigname *big_free = NULL;
static int bignames_left, hash_size;
static void make_non_terminals(struct crec *source);
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
static const struct {
unsigned int type;
@@ -68,7 +70,8 @@ static const struct {
{ 252, "AXFR" },
{ 253, "MAILB" },
{ 254, "MAILA" },
{ 255, "ANY" }
{ 255, "ANY" },
{ 257, "CAA" }
};
static void cache_free(struct crec *crecp);
@@ -556,7 +559,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
free_avail = 1; /* Must be free space now. */
cache_scan_free(cache_get_name(new), &free_addr, now, new->flags, NULL, NULL);
cache_live_freed++;
daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;
}
else
{
@@ -641,13 +644,27 @@ void cache_end_insert(void)
{
cache_hash(new_chain);
cache_link(new_chain);
cache_inserted++;
daemon->metrics[METRIC_DNS_CACHE_INSERTED]++;
}
new_chain = tmp;
}
new_chain = NULL;
}
int cache_find_non_terminal(char *name, time_t now)
{
struct crec *crecp;
for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
if (!is_outdated_cname_pointer(crecp) &&
!is_expired(now, crecp) &&
(crecp->flags & F_FORWARD) &&
hostname_isequal(name, cache_get_name(crecp)))
return 1;
return 0;
}
struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
{
struct crec *ans;
@@ -818,6 +835,8 @@ static void add_hosts_cname(struct crec *target)
crec->addr.cname.uid = target->uid;
crec->uid = UID_NONE;
cache_hash(crec);
make_non_terminals(crec);
add_hosts_cname(crec); /* handle chains */
}
}
@@ -889,6 +908,7 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
cache->uid = index;
memcpy(&cache->addr.addr, addr, addrlen);
cache_hash(cache);
make_non_terminals(cache);
/* don't need to do alias stuff for second and subsequent addresses. */
if (!nameexists)
@@ -1059,7 +1079,8 @@ void cache_reload(void)
struct ds_config *ds;
#endif
cache_inserted = cache_live_freed = 0;
daemon->metrics[METRIC_DNS_CACHE_INSERTED] = 0;
daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED] = 0;
for (i=0; i<hash_size; i++)
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
@@ -1101,6 +1122,7 @@ void cache_reload(void)
cache->addr.cname.uid = SRC_INTERFACE;
cache->uid = UID_NONE;
cache_hash(cache);
make_non_terminals(cache);
add_hosts_cname(cache); /* handle chains */
}
@@ -1118,6 +1140,7 @@ void cache_reload(void)
cache->addr.ds.digest = ds->digest_type;
cache->uid = ds->class;
cache_hash(cache);
make_non_terminals(cache);
}
#endif
@@ -1233,6 +1256,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
aliasc->addr.cname.uid = target->uid;
aliasc->uid = UID_NONE;
cache_hash(aliasc);
make_non_terminals(aliasc);
add_dhcp_cname(aliasc, ttd);
}
}
@@ -1321,12 +1345,104 @@ void cache_add_dhcp_entry(char *host_name, int prot,
crec->name.namep = host_name;
crec->uid = UID_NONE;
cache_hash(crec);
make_non_terminals(crec);
add_dhcp_cname(crec, ttd);
}
}
#endif
/* Called when we put a local or DHCP name into the cache.
Creates empty cache entries for subnames (ie,
for three.two.one, for two.one and one), without
F_IPV4 or F_IPV6 or F_CNAME set. These convert
NXDOMAIN answers to NoData ones. */
static void make_non_terminals(struct crec *source)
{
char *name = cache_get_name(source);
struct crec* crecp, *tmp, **up;
int type = F_HOSTS | F_CONFIG;
#ifdef HAVE_DHCP
if (source->flags & F_DHCP)
type = F_DHCP;
#endif
/* First delete any empty entries for our new real name. Note that
we only delete empty entries deriving from DHCP for a new DHCP-derived
entry and vice-versa for HOSTS and CONFIG. This ensures that
non-terminals from DHCP go when we reload DHCP and
for HOSTS/CONFIG when we re-read. */
for (up = hash_bucket(name), crecp = *up; crecp; crecp = tmp)
{
tmp = crecp->hash_next;
if (!is_outdated_cname_pointer(crecp) &&
(crecp->flags & F_FORWARD) &&
(crecp->flags & type) &&
!(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS)) &&
hostname_isequal(name, cache_get_name(crecp)))
{
*up = crecp->hash_next;
#ifdef HAVE_DHCP
if (type & F_DHCP)
{
crecp->next = dhcp_spare;
dhcp_spare = crecp;
}
else
#endif
free(crecp);
break;
}
else
up = &crecp->hash_next;
}
while ((name = strchr(name, '.')))
{
name++;
/* Look for one existing, don't need another */
for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
if (!is_outdated_cname_pointer(crecp) &&
(crecp->flags & F_FORWARD) &&
(crecp->flags & type) &&
hostname_isequal(name, cache_get_name(crecp)))
break;
if (crecp)
{
/* If the new name expires later, transfer that time to
empty non-terminal entry. */
if (!(crecp->flags & F_IMMORTAL))
{
if (source->flags & F_IMMORTAL)
crecp->flags |= F_IMMORTAL;
else if (difftime(crecp->ttd, source->ttd) < 0)
crecp->ttd = source->ttd;
}
continue;
}
#ifdef HAVE_DHCP
if ((source->flags & F_DHCP) && dhcp_spare)
{
crecp = dhcp_spare;
dhcp_spare = dhcp_spare->next;
}
else
#endif
crecp = whine_malloc(sizeof(struct crec));
*crecp = *source;
crecp->flags &= ~(F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_REVERSE);
crecp->flags |= F_NAMEP;
crecp->name.namep = name;
cache_hash(crecp);
}
}
#ifndef NO_ID
int cache_make_stat(struct txt_record *t)
{
@@ -1348,24 +1464,24 @@ int cache_make_stat(struct txt_record *t)
break;
case TXT_STAT_INSERTS:
sprintf(buff+1, "%d", cache_inserted);
sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
break;
case TXT_STAT_EVICTIONS:
sprintf(buff+1, "%d", cache_live_freed);
sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]);
break;
case TXT_STAT_MISSES:
sprintf(buff+1, "%u", daemon->queries_forwarded);
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]);
break;
case TXT_STAT_HITS:
sprintf(buff+1, "%u", daemon->local_answer);
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
break;
#ifdef HAVE_AUTH
case TXT_STAT_AUTH:
sprintf(buff+1, "%u", daemon->auth_answer);
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
break;
#endif
@@ -1442,15 +1558,14 @@ static char *sanitise(char *name)
void dump_cache(time_t now)
{
struct server *serv, *serv1;
char *t = "";
my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
daemon->cachesize, cache_live_freed, cache_inserted);
daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
daemon->queries_forwarded, daemon->local_answer);
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
#ifdef HAVE_AUTH
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->auth_answer);
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
#endif
#ifdef HAVE_DNSSEC
blockdata_report();
@@ -1488,6 +1603,7 @@ void dump_cache(time_t now)
for (i=0; i<hash_size; i++)
for (cache = hash_table[i]; cache; cache = cache->hash_next)
{
char *t = " ";
char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
*a = 0;
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
@@ -1588,9 +1704,13 @@ char *querystr(char *desc, unsigned short type)
break;
}
len += 3; /* braces, terminator */
len += strlen(desc);
if (desc)
{
len += 2; /* braces */
len += strlen(desc);
}
len++; /* terminator */
if (!buff || bufflen < len)
{
if (buff)
@@ -1604,12 +1724,22 @@ char *querystr(char *desc, unsigned short type)
if (buff)
{
if (types)
sprintf(buff, "%s[%s]", desc, types);
if (desc)
{
if (types)
sprintf(buff, "%s[%s]", desc, types);
else
sprintf(buff, "%s[type=%d]", desc, type);
}
else
sprintf(buff, "%s[type=%d]", desc, type);
{
if (types)
sprintf(buff, "<%s>", types);
else
sprintf(buff, "type=%d", type);
}
}
return buff ? buff : "";
}
+3
View File
@@ -94,6 +94,9 @@ HAVE_DBUS
support some methods to allow (re)configuration of the upstream DNS
servers via DBus.
HAVE_UBUS
define this if you want to link against libubus
HAVE_IDN
define this if you want international domain name 2003 support.
+31
View File
@@ -85,6 +85,9 @@ const char* introspection_xml_template =
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
" </method>\n"
#endif
" <method name=\"GetMetrics\">\n"
" <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
" </method>\n"
" </interface>\n"
"</node>\n";
@@ -613,6 +616,30 @@ static DBusMessage *dbus_del_lease(DBusMessage* message)
}
#endif
static DBusMessage *dbus_get_metrics(DBusMessage* message)
{
DBusMessage *reply = dbus_message_new_method_return(message);
DBusMessageIter array, dict, iter;
int i;
dbus_message_iter_init_append(reply, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &array);
for (i = 0; i < __METRIC_MAX; i++) {
const char *key = get_metric_name(i);
dbus_uint32_t value = daemon->metrics[i];
dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
dbus_message_iter_append_basic(&dict, DBUS_TYPE_UINT32, &value);
dbus_message_iter_close_container(&array, &dict);
}
dbus_message_iter_close_container(&iter, &array);
return reply;
}
DBusHandlerResult message_handler(DBusConnection *connection,
DBusMessage *message,
void *user_data)
@@ -680,6 +707,10 @@ DBusHandlerResult message_handler(DBusConnection *connection,
reply = dbus_del_lease(message);
}
#endif
else if (strcmp(method, "GetMetrics") == 0)
{
reply = dbus_get_metrics(message);
}
else if (strcmp(method, "ClearCache") == 0)
clear_cache = 1;
else
+1
View File
@@ -76,6 +76,7 @@
#define T_AXFR 252
#define T_MAILB 253
#define T_ANY 255
#define T_CAA 257
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
+20 -5
View File
@@ -216,7 +216,7 @@ int main (int argc, char **argv)
#endif
#ifndef HAVE_AUTH
if (daemon->authserver)
if (daemon->authserver || daemon->auth_zones)
die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
#endif
@@ -225,13 +225,18 @@ int main (int argc, char **argv)
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
#endif
#ifndef HAVE_UBUS
if (option_bool(OPT_UBUS))
die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
#endif
if (daemon->max_port < daemon->min_port)
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
now = dnsmasq_time();
/* Create a serial at startup if not configured. */
if (daemon->authinterface && daemon->soa_sn == 0)
if (daemon->auth_zones && daemon->soa_sn == 0)
#ifdef HAVE_BROKEN_RTC
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
#else
@@ -947,8 +952,13 @@ int main (int argc, char **argv)
#ifdef HAVE_DBUS
set_dbus_listeners();
#endif
#endif
#ifdef HAVE_UBUS
if (option_bool(OPT_UBUS))
set_ubus_listeners();
#endif
#ifdef HAVE_DHCP
if (daemon->dhcp || daemon->relay4)
{
@@ -1078,7 +1088,12 @@ int main (int argc, char **argv)
}
check_dbus_listeners();
#endif
#ifdef HAVE_UBUS
if (option_bool(OPT_UBUS))
check_ubus_listeners();
#endif
check_dns_listeners(now);
#ifdef HAVE_TFTP
+21 -2
View File
@@ -57,6 +57,7 @@
#include "config.h"
#include "ip6addr.h"
#include "metrics.h"
typedef unsigned char u8;
typedef unsigned short u16;
@@ -254,7 +255,8 @@ struct event_desc {
#define OPT_MAC_HEX 55
#define OPT_TFTP_APREF_MAC 56
#define OPT_RAPID_COMMIT 57
#define OPT_LAST 58
#define OPT_UBUS 58
#define OPT_LAST 59
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
@@ -820,6 +822,13 @@ struct dhcp_boot {
struct dhcp_boot *next;
};
struct dhcp_match_name {
char *name;
int wildcard;
struct dhcp_netid *netid;
struct dhcp_match_name *next;
};
struct pxe_service {
unsigned short CSA, type;
char *menu, *basename, *sname;
@@ -1012,6 +1021,7 @@ extern struct daemon {
struct ra_interface *ra_interfaces;
struct dhcp_config *dhcp_conf;
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
struct dhcp_match_name *dhcp_name_match;
struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
@@ -1040,6 +1050,7 @@ extern struct daemon {
char *dump_file;
int dump_mask;
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
u32 metrics[__METRIC_MAX];
#ifdef OPTION6_PREFIX_CLASS
struct prefix_class *prefix_classes;
#endif
@@ -1060,7 +1071,6 @@ extern struct daemon {
int dnssec_no_time_check;
int back_to_the_future;
#endif
unsigned int local_answer, queries_forwarded, auth_answer;
struct frec *frec_list;
struct serverfd *sfds;
struct irec *interfaces;
@@ -1125,6 +1135,7 @@ void next_uid(struct crec *crecp);
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
char *record_source(unsigned int index);
char *querystr(char *desc, unsigned short type);
int cache_find_non_terminal(char *name, time_t now);
struct crec *cache_find_by_addr(struct crec *crecp,
struct all_addr *addr, time_t now,
unsigned int prot);
@@ -1240,6 +1251,7 @@ void *whine_malloc(size_t size);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
int hostname_isequal(const char *a, const char *b);
int hostname_issubdomain(char *a, char *b);
time_t dnsmasq_time(void);
int netmask_length(struct in_addr mask);
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
@@ -1445,6 +1457,13 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
# endif
#endif
/* ubus.c */
#ifdef HAVE_UBUS
void set_ubus_listeners(void);
void check_ubus_listeners(void);
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
#endif
/* ipset.c */
#ifdef HAVE_IPSET
void ipset_init(void);
+32 -12
View File
@@ -118,6 +118,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
unsigned int matchlen = 0;
struct server *serv;
unsigned int flags = 0;
static struct all_addr zero;
for (serv = daemon->servers; serv; serv=serv->next)
if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
@@ -129,9 +130,16 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
*type = SERV_FOR_NODOTS;
if (serv->flags & SERV_NO_ADDR)
flags = F_NXDOMAIN;
else if (serv->flags & SERV_LITERAL_ADDRESS)
else if (serv->flags & SERV_LITERAL_ADDRESS)
{
if (sflag & qtype)
/* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
{
memset(&zero, 0, sizeof(zero));
flags = qtype;
*addrpp = &zero;
}
else if (sflag & qtype)
{
flags = sflag;
if (serv->addr.sa.sa_family == AF_INET)
@@ -184,7 +192,14 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
flags = F_NXDOMAIN;
else if (serv->flags & SERV_LITERAL_ADDRESS)
{
if (sflag & qtype)
/* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
{
memset(&zero, 0, sizeof(zero));
flags = qtype;
*addrpp = &zero;
}
else if (sflag & qtype)
{
flags = sflag;
if (serv->addr.sa.sa_family == AF_INET)
@@ -246,9 +261,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
unsigned int crc = questions_crc(header, plen, daemon->namebuff);
void *hash = &crc;
#endif
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
(void)do_bit;
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
(void)do_bit;
/* may be no servers available. */
if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
@@ -399,7 +414,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct server *firstsentto = start;
int subnet, forwarded = 0;
size_t edns0_len;
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
unsigned char *pheader;
/* If a query is retried, use the log_id for the retry when logging the answer. */
@@ -554,6 +568,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (udpfd != -1)
{
plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
if (oph)
plen = add_pseudoheader(header, plen, ((unsigned char *) header) + PACKETSZ, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
}
@@ -1553,7 +1569,7 @@ void receive_query(struct listener *listen, time_t now)
{
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
daemon->auth_answer++;
daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
}
}
else
@@ -1571,13 +1587,13 @@ void receive_query(struct listener *listen, time_t now)
{
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
daemon->local_answer++;
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
}
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
header, (size_t)n, now, NULL, ad_reqd, do_bit))
daemon->queries_forwarded++;
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
else
daemon->local_answer++;
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
}
}
@@ -2104,7 +2120,11 @@ unsigned char *tcp_request(int confd, time_t now,
/* In case of local answer or no connections made. */
if (m == 0)
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
{
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
if (have_pseudoheader)
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
}
}
}
+9 -2
View File
@@ -555,7 +555,9 @@ void lease_prune(struct dhcp_lease *target, time_t now)
file_dirty = 1;
if (lease->hostname)
dns_dirty = 1;
daemon->metrics[lease->addr.s_addr ? METRIC_LEASES_PRUNED_4 : METRIC_LEASES_PRUNED_6]++;
*up = lease->next; /* unlink */
/* Put on old_leases list 'till we
@@ -773,7 +775,10 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr)
{
struct dhcp_lease *lease = lease_allocate();
if (lease)
lease->addr = addr;
{
lease->addr = addr;
daemon->metrics[METRIC_LEASES_ALLOCATED_4]++;
}
return lease;
}
@@ -788,6 +793,8 @@ struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
lease->addr6 = *addrp;
lease->flags |= lease_type;
lease->iaid = 0;
daemon->metrics[METRIC_LEASES_ALLOCATED_6]++;
}
return lease;
+44
View File
@@ -0,0 +1,44 @@
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
const char * metric_names[] = {
"dns_cache_inserted",
"dns_cache_live_freed",
"dns_queries_forwarded",
"dns_auth_answered",
"dns_local_answered",
"bootp",
"pxe",
"dhcp_ack",
"dhcp_decline",
"dhcp_discover",
"dhcp_inform",
"dhcp_nak",
"dhcp_offer",
"dhcp_release",
"dhcp_request",
"noanswer",
"leases_allocated_4",
"leases_pruned_4",
"leases_allocated_6",
"leases_pruned_6",
};
const char* get_metric_name(int i) {
return metric_names[i];
}
+43
View File
@@ -0,0 +1,43 @@
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* If you modify this list, please keep the labels in metrics.c in sync. */
enum {
METRIC_DNS_CACHE_INSERTED,
METRIC_DNS_CACHE_LIVE_FREED,
METRIC_DNS_QUERIES_FORWARDED,
METRIC_DNS_AUTH_ANSWERED,
METRIC_DNS_LOCAL_ANSWERED,
METRIC_BOOTP,
METRIC_PXE,
METRIC_DHCPACK,
METRIC_DHCPDECLINE,
METRIC_DHCPDISCOVER,
METRIC_DHCPINFORM,
METRIC_DHCPNAK,
METRIC_DHCPOFFER,
METRIC_DHCPRELEASE,
METRIC_DHCPREQUEST,
METRIC_NOANSWER,
METRIC_LEASES_ALLOCATED_4,
METRIC_LEASES_PRUNED_4,
METRIC_LEASES_ALLOCATED_6,
METRIC_LEASES_PRUNED_6,
__METRIC_MAX,
};
const char* get_metric_name(int);
+75 -14
View File
@@ -163,6 +163,9 @@ struct myoption {
#define LOPT_RAPID_COMMIT 351
#define LOPT_DUMPFILE 352
#define LOPT_DUMPMASK 353
#define LOPT_UBUS 354
#define LOPT_NAME_MATCH 355
#define LOPT_CAA 356
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -231,8 +234,10 @@ static const struct myoption opts[] =
{ "srv-host", 1, 0, 'W' },
{ "localise-queries", 0, 0, 'y' },
{ "txt-record", 1, 0, 'Y' },
{ "caa-record", 1, 0 , LOPT_CAA },
{ "dns-rr", 1, 0, LOPT_RR },
{ "enable-dbus", 2, 0, '1' },
{ "enable-ubus", 0, 0, LOPT_UBUS },
{ "bootp-dynamic", 2, 0, '3' },
{ "dhcp-mac", 1, 0, '4' },
{ "no-ping", 0, 0, '5' },
@@ -271,7 +276,8 @@ static const struct myoption opts[] =
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
{ "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
{ "all-servers", 0, 0, LOPT_NOLAST },
{ "dhcp-match", 1, 0, LOPT_MATCH },
{ "dhcp-match", 1, 0, LOPT_MATCH },
{ "dhcp-name-match", 1, 0, LOPT_NAME_MATCH },
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL },
@@ -420,6 +426,7 @@ static struct {
{ 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
{ '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
{ LOPT_UBUS, OPT_UBUS, NULL, gettext_noop("Enable the UBus interface."), NULL },
{ '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
@@ -453,6 +460,7 @@ static struct {
{ LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
{ LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
{ LOPT_NAME_MATCH, ARG_DUP, "set:<tag>,<string>[*]", gettext_noop("Set tag if client provides given name."), NULL },
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
@@ -475,6 +483,7 @@ static struct {
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
{ LOPT_CAA, ARG_DUP, "<name>,<flags>,<tag>,<value>", gettext_noop("Specify certification authority authorization record"), NULL },
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
@@ -1746,7 +1755,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
#endif
}
break;
case 'x': /* --pid-file */
daemon->runfile = opt_string_alloc(arg);
break;
@@ -1892,8 +1901,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
}
#ifdef HAVE_AUTH
case LOPT_AUTHSERV: /* --auth-server */
if (!(comma = split(arg)))
ret_err(gen_err);
@@ -2068,7 +2075,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
break;
#endif
case 's': /* --domain */
case LOPT_SYNTH: /* --synth-domain */
@@ -2229,7 +2235,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
char *star;
new->next = daemon->synth_domains;
daemon->synth_domains = new;
if ((star = strrchr(new->prefix, '*')) && *(star+1) == 0)
if (new->prefix &&
(star = strrchr(new->prefix, '*'))
&& *(star+1) == 0)
{
*star = 0;
new->indexed = 1;
@@ -2459,11 +2467,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
else if (strcmp(arg, "#") == 0)
{
newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
if (newlist->flags & SERV_LITERAL_ADDRESS)
ret_err(gen_err);
}
newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
else
{
char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
@@ -3284,7 +3288,33 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
option == LOPT_FORCE ? DHOPT_FORCE :
(option == LOPT_MATCH ? DHOPT_MATCH :
(option == LOPT_OPTS ? DHOPT_BANK : 0)));
case LOPT_NAME_MATCH: /* --dhcp-name-match */
{
struct dhcp_match_name *new = opt_malloc(sizeof(struct dhcp_match_name));
struct dhcp_netid *id = opt_malloc(sizeof(struct dhcp_netid));
ssize_t len;
if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
ret_err(gen_err);
new->wildcard = 0;
new->netid = id;
id->net = opt_string_alloc(set_prefix(arg));
if (comma[len-1] == '*')
{
comma[len-1] = 0;
new->wildcard = 1;
}
new->name = opt_string_alloc(comma);
new->next = daemon->dhcp_name_match;
daemon->dhcp_name_match = new;
break;
}
case 'M': /* --dhcp-boot */
{
struct dhcp_netid *id = NULL;
@@ -3971,7 +4001,7 @@ err:
if (data)
{
new->txt=opt_malloc(len);
new->txt = opt_malloc(len);
new->len = len;
memcpy(new->txt, data, len);
}
@@ -3979,6 +4009,37 @@ err:
break;
}
case LOPT_CAA: /* --caa-record */
{
struct txt_record *new;
char *tag, *value;
int flags;
comma = split(arg);
tag = split(comma);
value = split(tag);
new = opt_malloc(sizeof(struct txt_record));
new->next = daemon->rr;
daemon->rr = new;
if (!atoi_check(comma, &flags) || !tag || !value || !(new->name = canonicalise_opt(arg)))
ret_err(_("bad CAA record"));
unhide_metas(tag);
unhide_metas(value);
new->len = strlen(tag) + strlen(value) + 2;
new->txt = opt_malloc(new->len);
new->txt[0] = flags;
new->txt[1] = strlen(tag);
memcpy(&new->txt[2], tag, strlen(tag));
memcpy(&new->txt[2 + strlen(tag)], value, strlen(value));
new->class = T_CAA;
break;
}
case 'Y': /* --txt-record */
{
struct txt_record *new;
@@ -4336,7 +4397,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
if (errmess)
strcpy(daemon->namebuff, errmess);
if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV))
if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV))
{
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
if (hard_opt != 0)
+11 -16
View File
@@ -986,40 +986,35 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
int check_for_local_domain(char *name, time_t now)
{
struct crec *crecp;
struct mx_srv_record *mx;
struct txt_record *txt;
struct interface_name *intr;
struct ptr_record *ptr;
struct naptr *naptr;
/* Note: the call to cache_find_by_name is intended to find any record which matches
ie A, AAAA, CNAME. */
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) &&
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
return 1;
for (naptr = daemon->naptr; naptr; naptr = naptr->next)
if (hostname_isequal(name, naptr->name))
if (hostname_issubdomain(name, naptr->name))
return 1;
for (mx = daemon->mxnames; mx; mx = mx->next)
if (hostname_isequal(name, mx->name))
if (hostname_issubdomain(name, mx->name))
return 1;
for (txt = daemon->txt; txt; txt = txt->next)
if (hostname_isequal(name, txt->name))
if (hostname_issubdomain(name, txt->name))
return 1;
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(name, intr->name))
if (hostname_issubdomain(name, intr->name))
return 1;
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
if (hostname_isequal(name, ptr->name))
if (hostname_issubdomain(name, ptr->name))
return 1;
if (cache_find_non_terminal(name, now))
return 1;
return 0;
}
@@ -1382,11 +1377,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
sec_data = 0;
if (!dryrun)
{
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, t->class));
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
t->class, C_IN, "t", t->len, t->txt))
anscount ++;
anscount++;
}
}
+51 -2
View File
@@ -626,6 +626,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
}
daemon->metrics[METRIC_BOOTP]++;
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
@@ -699,8 +700,39 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
client_hostname = daemon->dhcp_buff;
}
if (client_hostname && option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
if (client_hostname)
{
struct dhcp_match_name *m;
size_t nl = strlen(client_hostname);
if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
for (m = daemon->dhcp_name_match; m; m = m->next)
{
size_t ml = strlen(m->name);
char save = 0;
if (nl < ml)
continue;
if (nl > ml)
{
save = client_hostname[ml];
client_hostname[ml] = 0;
}
if (hostname_isequal(client_hostname, m->name) &&
(save == 0 || m->wildcard))
{
m->netid->next = netid;
netid = m->netid;
}
if (save != 0)
client_hostname[ml] = save;
}
}
if (have_config(config, CONFIG_NAME))
{
@@ -928,6 +960,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if ((pxe && !workaround) || !redirect4011)
do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
daemon->metrics[METRIC_PXE]++;
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
log_tags(tagif_netid, ntohl(mess->xid));
if (!ignore)
@@ -962,6 +995,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
return 0;
daemon->metrics[METRIC_DHCPDECLINE]++;
log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
@@ -994,6 +1028,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
message = _("unknown lease");
daemon->metrics[METRIC_DHCPRELEASE]++;
log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
return 0;
@@ -1060,6 +1095,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
message = _("no address available");
}
daemon->metrics[METRIC_DHCPDISCOVER]++;
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
@@ -1080,6 +1116,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
goto rapid_commit;
}
daemon->metrics[METRIC_DHCPOFFER]++;
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
@@ -1192,6 +1229,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
mess->yiaddr = mess->ciaddr;
}
daemon->metrics[METRIC_DHCPREQUEST]++;
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
rapid_commit:
@@ -1265,6 +1303,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (message)
{
daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
/* rapid commit case: lease allocate failed but don't send DHCPNAK */
@@ -1426,6 +1465,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
override = lease->override;
daemon->metrics[METRIC_DHCPACK]++;
log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
clear_packet(mess, end);
@@ -1444,6 +1484,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (ignore || have_config(config, CONFIG_DISABLE))
message = _("ignored");
daemon->metrics[METRIC_DHCPINFORM]++;
log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
if (message || mess->ciaddr.s_addr == 0)
@@ -1470,6 +1511,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
log_tags(tagif_netid, ntohl(mess->xid));
daemon->metrics[METRIC_DHCPACK]++;
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
if (lease)
@@ -1636,6 +1678,13 @@ static void log_packet(char *type, void *addr, unsigned char *ext_mac,
daemon->namebuff,
string ? string : "",
err ? err : "");
#ifdef HAVE_UBUS
if (!strcmp(type, "DHCPACK"))
ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
else if (!strcmp(type, "DHCPRELEASE"))
ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
#endif
}
static void log_options(unsigned char *start, u32 xid)
+61 -43
View File
@@ -639,9 +639,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
int plain_range = 1;
u32 lease_time;
struct dhcp_lease *ltmp;
struct in6_addr *req_addr;
struct in6_addr addr;
struct in6_addr req_addr, addr;
if (!check_ia(state, opt, &ia_end, &ia_option))
continue;
@@ -709,9 +708,10 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
req_addr = opt6_ptr(ia_option, 0);
/* worry about alignment here. */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
if ((c = address6_valid(state->context, &req_addr, solicit_tags, plain_range)))
{
lease_time = c->lease_time;
/* If the client asks for an address on the same network as a configured address,
@@ -719,14 +719,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
addresses automatic. */
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
{
req_addr = &addr;
req_addr = addr;
mark_config_used(c, &addr);
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
}
else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
continue; /* not an address we're allowed */
else if (!check_address(state, req_addr))
else if (!check_address(state, &req_addr))
continue; /* address leased elsewhere */
/* add address to output packet */
@@ -734,8 +734,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
add_address(state, c, lease_time, ia_option, &min_time, req_addr, now);
mark_context_used(state, req_addr);
add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
mark_context_used(state, &req_addr);
get_context_tag(state, c);
address_assigned = 1;
}
@@ -768,15 +768,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ltmp = NULL;
while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
{
req_addr = &ltmp->addr6;
if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
req_addr = ltmp->addr6;
if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
add_address(state, c, c->lease_time, NULL, &min_time, req_addr, now);
mark_context_used(state, req_addr);
add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
mark_context_used(state, &req_addr);
get_context_tag(state, c);
address_assigned = 1;
}
@@ -892,16 +892,19 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
struct in6_addr req_addr;
struct dhcp_context *dynamic, *c;
unsigned int lease_time;
struct in6_addr addr;
int config_ok = 0;
/* align. */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((c = address6_valid(state->context, req_addr, tagif, 1)))
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr);
if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
{
if (!dynamic && !config_ok)
{
@@ -911,7 +914,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
else if (!check_address(state, req_addr))
else if (!check_address(state, &req_addr))
{
/* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE);
@@ -933,7 +936,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
add_address(state, dynamic, lease_time, ia_option, &min_time, &req_addr, now);
get_context_tag(state, dynamic);
address_assigned = 1;
}
@@ -996,15 +999,17 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease = NULL;
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
struct in6_addr req_addr;
unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
unsigned int valid_time = opt6_uint(ia_option, 20, 4);
char *message = NULL;
struct dhcp_context *this_context;
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if (!(lease = lease6_find(state->clid, state->clid_len,
state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
state->iaid, req_addr)))
state->iaid, &req_addr)))
{
/* If the server cannot find a client entry for the IA the server
returns the IA containing no addresses with a Status Code option set
@@ -1012,7 +1017,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
save_counter(iacntr);
t1cntr = 0;
log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING);
@@ -1024,15 +1029,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
(this_context = address6_valid(state->context, req_addr, tagif, 1)))
if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
(this_context = address6_valid(state->context, &req_addr, tagif, 1)))
{
struct in6_addr addr;
unsigned int lease_time;
get_context_tag(state, this_context);
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr) && have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
else
lease_time = this_context->lease_time;
@@ -1045,7 +1050,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
if (state->ia_type == OPTION6_IA_NA && state->hostname)
{
char *addr_domain = get_domain6(req_addr);
char *addr_domain = get_domain6(&req_addr);
if (!state->send_domain)
state->send_domain = addr_domain;
lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
@@ -1063,12 +1068,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
if (message && (message != state->hostname))
log6_packet(state, "DHCPREPLY", req_addr, message);
log6_packet(state, "DHCPREPLY", &req_addr, message);
else
log6_quiet(state, "DHCPREPLY", req_addr, message);
log6_quiet(state, "DHCPREPLY", &req_addr, message);
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(req_addr, sizeof(*req_addr));
put_opt6(&req_addr, sizeof(req_addr));
put_opt6_long(preferred_time);
put_opt6_long(valid_time);
end_opt6(o1);
@@ -1100,20 +1105,23 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option;
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
struct in6_addr req_addr;
/* alignment */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if (!address6_valid(state->context, req_addr, tagif, 1))
if (!address6_valid(state->context, &req_addr, tagif, 1))
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
put_opt6_string(_("confirm failed"));
end_opt6(o1);
log6_quiet(state, "DHCPREPLY", req_addr, _("confirm failed"));
log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
return 1;
}
good_addr = 1;
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
}
}
@@ -1172,9 +1180,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease;
struct in6_addr addr;
/* align */
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
state->iaid, opt6_ptr(ia_option, 0))))
state->iaid, &addr)))
lease_prune(lease, now);
else
{
@@ -1191,7 +1202,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
put_opt6(&addr, IN6ADDRSZ);
put_opt6_long(0);
put_opt6_long(0);
end_opt6(o1);
@@ -1234,12 +1245,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease;
struct in6_addr *addrp = opt6_ptr(ia_option, 0);
struct in6_addr addr;
if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, addrp))
/* align */
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, &addr))
{
prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
daemon->addrbuff, daemon->dhcp_buff3);
config->flags |= CONFIG_DECLINED;
@@ -1251,7 +1265,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
context_tmp->addr_epoch++;
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
state->iaid, opt6_ptr(ia_option, 0))))
state->iaid, &addr)))
lease_prune(lease, now);
else
{
@@ -1268,7 +1282,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
o1 = new_opt6(OPTION6_IAADDR);
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
put_opt6(&addr, IN6ADDRSZ);
put_opt6_long(0);
put_opt6_long(0);
end_opt6(o1);
@@ -1936,7 +1950,11 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
}
else if (type == OPTION6_IAADDR)
{
inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
struct in6_addr addr;
/* align */
memcpy(&addr, opt6_ptr(opt, 0), IN6ADDRSZ);
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
sprintf(daemon->namebuff, "%s PL=%u VL=%u",
daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
optname = "iaaddr";
+107
View File
@@ -0,0 +1,107 @@
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#ifdef HAVE_UBUS
#include <libubus.h>
static struct ubus_context *ubus = NULL;
static struct blob_buf b;
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg);
static struct ubus_method ubus_object_methods[] = {
{.name = "metrics", .handler = ubus_handle_metrics},
};
static struct ubus_object_type ubus_object_type = UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
static struct ubus_object ubus_object = {
.name = "dnsmasq",
.type = &ubus_object_type,
.methods = ubus_object_methods,
.n_methods = ARRAY_SIZE(ubus_object_methods),
};
void set_ubus_listeners()
{
if (!ubus)
return;
poll_listen(ubus->sock.fd, POLLIN);
poll_listen(ubus->sock.fd, POLLERR);
poll_listen(ubus->sock.fd, POLLHUP);
}
void check_ubus_listeners()
{
if (!ubus)
{
ubus = ubus_connect(NULL);
if (!ubus)
return;
ubus_add_object(ubus, &ubus_object);
}
if (poll_check(ubus->sock.fd, POLLIN))
ubus_handle_event(ubus);
if (poll_check(ubus->sock.fd, POLLHUP))
{
ubus_free(ubus);
ubus = NULL;
}
}
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int i;
blob_buf_init(&b, 0);
for(i=0; i < __METRIC_MAX; i++)
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
ubus_send_reply(ctx, req, b.head);
return 0;
}
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
{
if (!ubus || !ubus_object.has_subscribers)
return;
blob_buf_init(&b, 0);
if (mac)
blobmsg_add_string(&b, "mac", mac);
if (ip)
blobmsg_add_string(&b, "ip", ip);
if (name)
blobmsg_add_string(&b, "name", name);
if (interface)
blobmsg_add_string(&b, "interface", interface);
ubus_notify(ubus, &ubus_object, type, b.head, -1);
}
#endif /* HAVE_UBUS */
+38
View File
@@ -355,6 +355,44 @@ int hostname_isequal(const char *a, const char *b)
return 1;
}
/* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */
int hostname_issubdomain(char *a, char *b)
{
char *ap, *bp;
unsigned int c1, c2;
/* move to the end */
for (ap = a; *ap; ap++);
for (bp = b; *bp; bp++);
/* a shorter than b or a empty. */
if ((bp - b) < (ap - a) || ap == a)
return 0;
do
{
c1 = (unsigned char) *(--ap);
c2 = (unsigned char) *(--bp);
if (c1 >= 'A' && c1 <= 'Z')
c1 += 'a' - 'A';
if (c2 >= 'A' && c2 <= 'Z')
c2 += 'a' - 'A';
if (c1 != c2)
return 0;
} while (ap != a);
if (bp == b)
return 2;
if (*(--bp) == '.')
return 1;
return 0;
}
time_t dnsmasq_time(void)
{
#ifdef HAVE_BROKEN_RTC