mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
459380965a | ||
|
|
21bac1bccd | ||
|
|
b1a1b6def5 | ||
|
|
baeb3adf21 | ||
|
|
39f6a04ca4 | ||
|
|
37c9ccebd1 | ||
|
|
71c73ac17c | ||
|
|
c6cb7407b3 | ||
|
|
333b2ceb97 |
No files matched your search
@@ -1,3 +1,24 @@
|
|||||||
|
version 2.66
|
||||||
|
Add the ability to act as an authoritative DNS
|
||||||
|
server. Dnsmasq can now answer queries from the wider 'net
|
||||||
|
with local data, as long as the correct NS records are set
|
||||||
|
up. Only local data is provided, to avoid creating an open
|
||||||
|
DNS relay. Zone transfer is supported, to allow secondary
|
||||||
|
servers to be configured.
|
||||||
|
|
||||||
|
Add "constructed DHCP ranges" for DHCPv6. This is intended
|
||||||
|
for IPv6 routers which get prefixes dynamically via prefix
|
||||||
|
delegation. With suitable configuration, stateful DHCPv6
|
||||||
|
and RA can happen automatically as prefixes are delegated
|
||||||
|
and then deprecated, without having to re-write the
|
||||||
|
dnsmasq configuration file or restart the daemon. Thanks to
|
||||||
|
Steven Barth for extensive testing and development work on
|
||||||
|
this idea.
|
||||||
|
|
||||||
|
Fix crash on startup on Solaris 11. Regression probably
|
||||||
|
introduced in 2.61. Thanks to Geoff Johnstone for the patch.
|
||||||
|
|
||||||
|
|
||||||
version 2.65
|
version 2.65
|
||||||
Fix regression which broke forwarding of queries sent via
|
Fix regression which broke forwarding of queries sent via
|
||||||
TCP which are not for A and AAAA and which were directed to
|
TCP which are not for A and AAAA and which were directed to
|
||||||
|
|||||||
+171
-2
@@ -75,6 +75,9 @@ the upstream DNS servers.
|
|||||||
.B --max-cache-ttl=<time>
|
.B --max-cache-ttl=<time>
|
||||||
Set a maximum TTL value for entries in the cache.
|
Set a maximum TTL value for entries in the cache.
|
||||||
.TP
|
.TP
|
||||||
|
.B --auth-ttl=<time>
|
||||||
|
Set the TTL value returned in answers from the authoritative server.
|
||||||
|
.TP
|
||||||
.B \-k, --keep-in-foreground
|
.B \-k, --keep-in-foreground
|
||||||
Do not go into the background at startup but otherwise run as
|
Do not go into the background at startup but otherwise run as
|
||||||
normal. This is intended for use when dnsmasq is run under daemontools
|
normal. This is intended for use when dnsmasq is run under daemontools
|
||||||
@@ -541,8 +544,27 @@ needed for a client to do validation itself.
|
|||||||
.TP
|
.TP
|
||||||
.B --auth-zone=<domain>[,<subnet>[,<subnet>.....]]
|
.B --auth-zone=<domain>[,<subnet>[,<subnet>.....]]
|
||||||
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
||||||
will be served, except that A and AAAA records must be in one of the specified subnets, or in a subnet corresponding to a contructed DHCP range. The subnet(s) are also used to define in-addr.arpa and ipv6.arpa domains which are served for reverse-DNS queries.
|
will be served, except that A and AAAA records must be in one of the
|
||||||
.TP
|
specified subnets, or in a subnet corresponding to a contructed DHCP
|
||||||
|
range. The subnet(s) are also used to define in-addr.arpa and
|
||||||
|
ipv6.arpa domains which are served for reverse-DNS queries.
|
||||||
|
.TP
|
||||||
|
.B --auth-soa=<serial>[,<hostmaster>[,<refresh>[,<retry>[,<expiry>]]]]
|
||||||
|
Specify fields in the SOA record associated with authoritative
|
||||||
|
zones. Note that this is optional, all the values are set to sane defaults.
|
||||||
|
.TP
|
||||||
|
.B --auth-sec-servers=<domain>[,<domain>[,<domain>...]]
|
||||||
|
Specify any secondary servers for a zone for which dnsmasq is
|
||||||
|
authoritative. These servers must be configured to get zone data from
|
||||||
|
dnsmasq by zone transfer, and answer queries for the same
|
||||||
|
authoritative zones and dnsmasq.
|
||||||
|
.TP
|
||||||
|
.B --auth-peer=<ip-address>[,<ip-address>[,<ip-address>...]]
|
||||||
|
Specify the addresses of secondary servers which are allowed to
|
||||||
|
initiate zone transfer (AXFR) requests for zones for which dnsmasq is
|
||||||
|
authoritative. If this option is not given, then AXFR requests wil be
|
||||||
|
accepted from any secondary.
|
||||||
|
.TP
|
||||||
.B --conntrack
|
.B --conntrack
|
||||||
Read the Linux connection track mark associated with incoming DNS
|
Read the Linux connection track mark associated with incoming DNS
|
||||||
queries and set the same mark value on upstream traffic used to answer
|
queries and set the same mark value on upstream traffic used to answer
|
||||||
@@ -1671,6 +1693,153 @@ parameter in a BOOTP request is used as a tag,
|
|||||||
as is the tag "bootp", allowing some control over the options returned to
|
as is the tag "bootp", allowing some control over the options returned to
|
||||||
different classes of hosts.
|
different classes of hosts.
|
||||||
|
|
||||||
|
.SH AUTHORITATIVE CONFIGURATION
|
||||||
|
.PP
|
||||||
|
Configuring dnsmasq to act as an authoritative DNS server is
|
||||||
|
complicated by the fact that it involves configuration of external DNS
|
||||||
|
servers to provide delegation. We will walk through three scenarios of
|
||||||
|
increasing complexity. Prerequisites for all of these scenarios
|
||||||
|
are a globally accesible IP address, an A or AAAA record pointing to that address,
|
||||||
|
and an external DNS server capable of doing delegation of the zone in
|
||||||
|
question. For the first part of this explanation, we will call the A (or AAAA) record
|
||||||
|
for the globally accessible address server.example.com, and the zone
|
||||||
|
for which dnsmasq is authoritative our.zone.com.
|
||||||
|
|
||||||
|
The simplest configuration consists of two lines of dnsmasq configuration; something like
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.B auth-server=server.example.com,eth0
|
||||||
|
.B auth=zone=our.zone.com,1.2.3.0/24
|
||||||
|
.fi
|
||||||
|
|
||||||
|
and two records in the external DNS
|
||||||
|
|
||||||
|
.nf
|
||||||
|
server.example.com A 192.0.43.10
|
||||||
|
our.zone.com NS server.example.com
|
||||||
|
.fi
|
||||||
|
|
||||||
|
eth0 is the external network interface on which dnsmasq is listening,
|
||||||
|
and has (globally accessible) address 192.0.43.10.
|
||||||
|
|
||||||
|
Note that the external IP address may well be dynamic (ie assigned
|
||||||
|
from an ISP by DHCP or PPP) If so, the A record must be linked to this
|
||||||
|
dynamic assignment by one of the usual dynamic-DNS systems.
|
||||||
|
|
||||||
|
A more complex, but practically useful configuration has the address
|
||||||
|
record for the globally accessible IP address residing in the
|
||||||
|
authoritative zone which dnsmasq is serving, typically at the root. Now
|
||||||
|
we have
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.B auth-server=our.zone.com,eth0
|
||||||
|
.B auth=zone=our.zone.com,1.2.3.0/24
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.nf
|
||||||
|
our.zone.com A 192.0.43.10
|
||||||
|
our.zone.com NS our.zone.com
|
||||||
|
.fi
|
||||||
|
|
||||||
|
The A record for our.zone.com has now become a glue record, it solves
|
||||||
|
the chicken-and-egg problem of finding the IP address of the
|
||||||
|
nameserver for our.zone.com when the A record is within that
|
||||||
|
zone. Note that this is the only role of this record: as dnsmasq is
|
||||||
|
now authoritative from our.zone.com it too must provide this
|
||||||
|
record. If the external address is static, this can be done with an
|
||||||
|
.B /etc/hosts
|
||||||
|
entry or
|
||||||
|
.B --host-record.
|
||||||
|
If the external address is dynamic,
|
||||||
|
then it must be done using something like
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.B --interface-name=our.zone.com,eth0
|
||||||
|
.fi
|
||||||
|
|
||||||
|
Our final configuration builds on that above, but also adds a
|
||||||
|
secondary DNS server. This is another DNS server which learns the DNS data
|
||||||
|
for the zone by doing zones transfer, and acts as a backup should
|
||||||
|
the primary server become inaccessible. The configuration of the
|
||||||
|
secondary is beyond the scope of this man-page, but the extra
|
||||||
|
configuration of dnsmasq is simple:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.B auth-sec-servers=secondary.myisp.com
|
||||||
|
.fi
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
.nf
|
||||||
|
our.zone.com NS secondary.myisp.com
|
||||||
|
.fi
|
||||||
|
|
||||||
|
Adding auth-sec-servers enables zone transfer in dnsmasq, to allow the
|
||||||
|
secondary to collect the DNS data. If you wish to restrict this data
|
||||||
|
to particular hosts then
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.B auth-peer=<IP address of secondary>
|
||||||
|
.fi
|
||||||
|
|
||||||
|
will do so.
|
||||||
|
|
||||||
|
Dnsmasq acts as an authoritative server for in-addr.arpa and
|
||||||
|
ipv6.arpa domains associated with the subnets given in auth-zone
|
||||||
|
declarations, so reverse (address to name) lookups can be simply
|
||||||
|
configured with a suitable NS record, for instance in this example,
|
||||||
|
where we allow 1.2.3.0/24 addresses.
|
||||||
|
|
||||||
|
.nf
|
||||||
|
3.2.1.in-addr.arpa NS our.zone.com
|
||||||
|
.fi
|
||||||
|
|
||||||
|
Note that at present, reverse (in-addr.arpa and ip6.arpa) zones are
|
||||||
|
not available in zone transfers, so there is no point arranging
|
||||||
|
secondary servers for reverse lookups.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
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.
|
||||||
|
.PP
|
||||||
|
.B --cname
|
||||||
|
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
|
||||||
|
authoritative zone name.
|
||||||
|
.PP
|
||||||
|
IPv4 and IPv6 addresses from /etc/hosts (and
|
||||||
|
.B --addn-hosts
|
||||||
|
) and
|
||||||
|
.B --host-record
|
||||||
|
provided the address falls into one of the subnets specified in the
|
||||||
|
.B --auth-zone.
|
||||||
|
.PP
|
||||||
|
Addresses specified by
|
||||||
|
.B --interface-name.
|
||||||
|
In this case, the address is not contrained to a subnet from
|
||||||
|
.B --auth-zone.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
Addresses of DHCP leases, provided the address falls into one of the subnets specified in the
|
||||||
|
.B --auth-zone
|
||||||
|
OR a constructed DHCP range. In the default mode, where a DHCP lease
|
||||||
|
has an unqualified name, and possibly a qualified name constructed
|
||||||
|
using
|
||||||
|
.B --domain
|
||||||
|
then the name in the authoritative zone is constructed from the
|
||||||
|
unqualified name and the zone's domain. This may or may not equal
|
||||||
|
that specified by
|
||||||
|
.B --domain.
|
||||||
|
If
|
||||||
|
.B --dhcp-fqdn
|
||||||
|
is set, then the fully qualified names associated with DHCP leases are
|
||||||
|
used, and must match the zone's domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.SH EXIT CODES
|
.SH EXIT CODES
|
||||||
.PP
|
.PP
|
||||||
0 - Dnsmasq successfully forked into the background, or terminated
|
0 - Dnsmasq successfully forked into the background, or terminated
|
||||||
|
|||||||
+20
-22
@@ -376,35 +376,33 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
else if (qtype == T_AXFR)
|
else if (qtype == T_AXFR)
|
||||||
{
|
{
|
||||||
if (daemon->auth_peers)
|
struct iname *peers;
|
||||||
|
|
||||||
|
if (peer_addr->sa.sa_family == AF_INET)
|
||||||
|
peer_addr->in.sin_port = 0;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
peer_addr->in6.sin6_port = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
||||||
|
if (sockaddr_isequal(peer_addr, &peers->addr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Refuse all AXFR unless --auth-sec-servers is set */
|
||||||
|
if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)
|
||||||
{
|
{
|
||||||
struct iname *peers;
|
|
||||||
|
|
||||||
if (peer_addr->sa.sa_family == AF_INET)
|
if (peer_addr->sa.sa_family == AF_INET)
|
||||||
peer_addr->in.sin_port = 0;
|
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
else
|
||||||
peer_addr->in6.sin6_port = 0;
|
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
|
||||||
if (sockaddr_isequal(peer_addr, &peers->addr))
|
return 0;
|
||||||
break;
|
|
||||||
|
|
||||||
if (!peers)
|
|
||||||
{
|
|
||||||
if (peer_addr->sa.sa_family == AF_INET)
|
|
||||||
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
|
||||||
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
soa = 1; /* inhibits auth section */
|
soa = 1; /* inhibits auth section */
|
||||||
ns = 1; /* ensure we include NS records! */
|
ns = 1; /* ensure we include NS records! */
|
||||||
axfr = 1;
|
axfr = 1;
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
{
|
{
|
||||||
int iface_index = if_nametoindex(addrs->ifa_name);
|
int iface_index = if_nametoindex(addrs->ifa_name);
|
||||||
|
|
||||||
if (iface_index == 0)
|
if (iface_index == 0 || !addrs->ifa_addr || !addrs->ifa_netmask)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
@@ -119,7 +119,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
struct in_addr addr, netmask, broadcast;
|
struct in_addr addr, netmask, broadcast;
|
||||||
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
||||||
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
||||||
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
if (addrs->ifa_broadaddr)
|
||||||
|
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
||||||
|
else
|
||||||
|
broadcast.s_addr = 0;
|
||||||
if (!((*callback)(addr, iface_index, netmask, broadcast, parm)))
|
if (!((*callback)(addr, iface_index, netmask, broadcast, parm)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-44
@@ -679,7 +679,7 @@ void log_context(int family, struct dhcp_context *context)
|
|||||||
|
|
||||||
void *start = &context->start;
|
void *start = &context->start;
|
||||||
void *end = &context->end;
|
void *end = &context->end;
|
||||||
char *n = "", *m = "", *p = daemon->namebuff;
|
char *template = "", *p = daemon->namebuff;
|
||||||
|
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
@@ -694,67 +694,59 @@ void log_context(int family, struct dhcp_context *context)
|
|||||||
end = &context->end6;
|
end = &context->end6;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((context->flags & CONTEXT_DHCP) ||
|
if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
|
||||||
!(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)))
|
strcpy(daemon->namebuff, _(", prefix deprecated"));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
|
p += sprintf(p, _(", lease time "));
|
||||||
strcpy(daemon->namebuff, _(", prefix deprecated"));
|
prettyprint_time(p, context->lease_time);
|
||||||
else
|
p += strlen(p);
|
||||||
{
|
}
|
||||||
p += sprintf(p, _(", lease time "));
|
|
||||||
m = p;
|
|
||||||
prettyprint_time(p, context->lease_time);
|
|
||||||
p += strlen(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (context->flags & CONTEXT_CONSTRUCTED)
|
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||||
{
|
{
|
||||||
char ifrn_name[IFNAMSIZ];
|
char ifrn_name[IFNAMSIZ];
|
||||||
if (indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, context->if_index, ifrn_name))
|
|
||||||
{
|
template = p;
|
||||||
n = p;
|
p += sprintf(p, ", ");
|
||||||
p += sprintf(p, ", constructed for %s", ifrn_name);
|
|
||||||
}
|
if (indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, context->if_index, ifrn_name))
|
||||||
}
|
sprintf(p, "constructed for %s", ifrn_name);
|
||||||
|
}
|
||||||
if (context->flags & CONTEXT_TEMPLATE)
|
else if (context->flags & CONTEXT_TEMPLATE)
|
||||||
{
|
{
|
||||||
n = p;
|
template = p;
|
||||||
p += sprintf(p, ", template for %s%s", context->template_interface,
|
p += sprintf(p, ", ");
|
||||||
(context->flags & CONTEXT_WILDCARD) ? "*" : "");
|
|
||||||
}
|
sprintf(p, "template for %s%s", context->template_interface,
|
||||||
|
(context->flags & CONTEXT_WILDCARD) ? "*" : "");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((context->flags & CONTEXT_DHCP) || family == AF_INET)
|
if ((context->flags & CONTEXT_DHCP) || family == AF_INET)
|
||||||
{
|
{
|
||||||
inet_ntop(family, start, daemon->dhcp_buff, 256);
|
inet_ntop(family, start, daemon->dhcp_buff, 256);
|
||||||
inet_ntop(family, end, daemon->dhcp_buff3, 256);
|
inet_ntop(family, end, daemon->dhcp_buff3, 256);
|
||||||
my_syslog(MS_DHCP | LOG_INFO,
|
my_syslog(MS_DHCP | LOG_INFO,
|
||||||
(context->flags & CONTEXT_RA_STATELESS) ?
|
(context->flags & CONTEXT_RA_STATELESS) ?
|
||||||
_("%s stateless on %s%.0s%.0s") :
|
_("%s stateless on %s%.0s%.0s%s") :
|
||||||
(context->flags & CONTEXT_STATIC) ?
|
(context->flags & CONTEXT_STATIC) ?
|
||||||
_("%s, static leases only on %.0s%s%s") :
|
_("%s, static leases only on %.0s%s%s%.0s") :
|
||||||
(context->flags & CONTEXT_PROXY) ?
|
(context->flags & CONTEXT_PROXY) ?
|
||||||
_("%s, proxy on subnet %.0s%s%.0s") :
|
_("%s, proxy on subnet %.0s%s%.0s%.0s") :
|
||||||
_("%s, IP range %s -- %s%s"),
|
_("%s, IP range %s -- %s%s%.0s"),
|
||||||
(family != AF_INET) ? "DHCPv6" : "DHCP",
|
(family != AF_INET) ? "DHCPv6" : "DHCP",
|
||||||
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff);
|
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff, template);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (context->flags & CONTEXT_RA_NAME)
|
if (context->flags & CONTEXT_RA_NAME)
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"),
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"), daemon->addrbuff, template);
|
||||||
daemon->addrbuff, n);
|
|
||||||
|
|
||||||
|
|
||||||
if (context->flags & CONTEXT_RA)
|
if ((context->flags & CONTEXT_RA) || (option_bool(OPT_RA) && (context->flags & CONTEXT_DHCP) && family == AF_INET6))
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s%s"),
|
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s"), daemon->addrbuff, template);
|
||||||
daemon->addrbuff,
|
|
||||||
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? "" : ", prefix valid ",
|
|
||||||
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? n : m);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-16
@@ -211,7 +211,8 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
{
|
{
|
||||||
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
if ((context->flags & CONTEXT_DHCP) &&
|
||||||
|
!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
prefix == context->prefix &&
|
prefix == context->prefix &&
|
||||||
is_same_net6(local, &context->start6, prefix) &&
|
is_same_net6(local, &context->start6, prefix) &&
|
||||||
is_same_net6(local, &context->end6, prefix))
|
is_same_net6(local, &context->end6, prefix))
|
||||||
@@ -328,6 +329,7 @@ int address6_allocate(struct dhcp_context *context, unsigned char *clid, int cl
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* can dynamically allocate addr */
|
||||||
struct dhcp_context *address6_available(struct dhcp_context *context,
|
struct dhcp_context *address6_available(struct dhcp_context *context,
|
||||||
struct in6_addr *taddr,
|
struct in6_addr *taddr,
|
||||||
struct dhcp_netid *netids)
|
struct dhcp_netid *netids)
|
||||||
@@ -352,6 +354,21 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* address OK if configured */
|
||||||
|
struct dhcp_context *address6_valid(struct dhcp_context *context,
|
||||||
|
struct in6_addr *taddr,
|
||||||
|
struct dhcp_netid *netids)
|
||||||
|
{
|
||||||
|
struct dhcp_context *tmp;
|
||||||
|
|
||||||
|
for (tmp = context; tmp; tmp = tmp->current)
|
||||||
|
if (is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
|
||||||
|
match_netid(tmp->filter, netids, 1))
|
||||||
|
return tmp;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct dhcp_context *narrow_context6(struct dhcp_context *context,
|
struct dhcp_context *narrow_context6(struct dhcp_context *context,
|
||||||
struct in6_addr *taddr,
|
struct in6_addr *taddr,
|
||||||
struct dhcp_netid *netids)
|
struct dhcp_netid *netids)
|
||||||
@@ -366,21 +383,12 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
|
|||||||
|
|
||||||
struct dhcp_context *tmp;
|
struct dhcp_context *tmp;
|
||||||
|
|
||||||
if (!(tmp = address6_available(context, taddr, netids)))
|
if (!(tmp = address6_available(context, taddr, netids)) &&
|
||||||
{
|
!(tmp = address6_valid(context, taddr, netids)))
|
||||||
for (tmp = context; tmp; tmp = tmp->current)
|
for (tmp = context; tmp; tmp = tmp->current)
|
||||||
if (match_netid(tmp->filter, netids, 1) &&
|
if (match_netid(tmp->filter, netids, 1) &&
|
||||||
is_same_net6(taddr, &tmp->start6, tmp->prefix) &&
|
is_same_net6(taddr, &tmp->start6, tmp->prefix))
|
||||||
(tmp->flags & CONTEXT_STATIC))
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
if (!tmp)
|
|
||||||
for (tmp = context; tmp; tmp = tmp->current)
|
|
||||||
if (match_netid(tmp->filter, netids, 1) &&
|
|
||||||
is_same_net6(taddr, &tmp->start6, tmp->prefix) &&
|
|
||||||
!(tmp->flags & CONTEXT_PROXY))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only one context allowed now */
|
/* Only one context allowed now */
|
||||||
if (tmp)
|
if (tmp)
|
||||||
|
|||||||
@@ -1149,6 +1149,9 @@ int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr);
|
|||||||
struct dhcp_context *address6_available(struct dhcp_context *context,
|
struct dhcp_context *address6_available(struct dhcp_context *context,
|
||||||
struct in6_addr *taddr,
|
struct in6_addr *taddr,
|
||||||
struct dhcp_netid *netids);
|
struct dhcp_netid *netids);
|
||||||
|
struct dhcp_context *address6_valid(struct dhcp_context *context,
|
||||||
|
struct in6_addr *taddr,
|
||||||
|
struct dhcp_netid *netids);
|
||||||
struct dhcp_context *narrow_context6(struct dhcp_context *context,
|
struct dhcp_context *narrow_context6(struct dhcp_context *context,
|
||||||
struct in6_addr *taddr,
|
struct in6_addr *taddr,
|
||||||
struct dhcp_netid *netids);
|
struct dhcp_netid *netids);
|
||||||
|
|||||||
+1
-1
@@ -392,7 +392,7 @@ static struct {
|
|||||||
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource 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_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 },
|
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
|
||||||
{ LOPT_AUTHZONE, ARG_DUP, "<domain>,<subnet>[,<subnet>]", gettext_noop("Domain to export to global DNS"), NULL },
|
{ LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
|
||||||
{ LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
|
{ LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
|
||||||
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
|
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
|
||||||
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
|
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
|
||||||
|
|||||||
+39
-31
@@ -82,18 +82,20 @@ static int dhcp6_maybe_relay(struct in6_addr *link_address, struct dhcp_netid **
|
|||||||
{
|
{
|
||||||
struct dhcp_context *c;
|
struct dhcp_context *c;
|
||||||
context = NULL;
|
context = NULL;
|
||||||
|
|
||||||
|
if (!IN6_IS_ADDR_LOOPBACK(link_address) &&
|
||||||
|
!IN6_IS_ADDR_LINKLOCAL(link_address) &&
|
||||||
|
!IN6_IS_ADDR_MULTICAST(link_address))
|
||||||
|
for (c = daemon->dhcp6; c; c = c->next)
|
||||||
|
if ((c->flags & CONTEXT_DHCP) &&
|
||||||
|
!(c->flags & CONTEXT_TEMPLATE) &&
|
||||||
|
is_same_net6(link_address, &c->start6, c->prefix) &&
|
||||||
|
is_same_net6(link_address, &c->end6, c->prefix))
|
||||||
|
{
|
||||||
|
c->current = context;
|
||||||
|
context = c;
|
||||||
|
}
|
||||||
|
|
||||||
for (c = daemon->dhcp6; c; c = c->next)
|
|
||||||
if (!IN6_IS_ADDR_LOOPBACK(link_address) &&
|
|
||||||
!IN6_IS_ADDR_LINKLOCAL(link_address) &&
|
|
||||||
!IN6_IS_ADDR_MULTICAST(link_address) &&
|
|
||||||
is_same_net6(link_address, &c->start6, c->prefix) &&
|
|
||||||
is_same_net6(link_address, &c->end6, c->prefix))
|
|
||||||
{
|
|
||||||
c->current = context;
|
|
||||||
context = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET6, link_address, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET6, link_address, daemon->addrbuff, ADDRSTRLEN);
|
||||||
@@ -525,32 +527,38 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
{
|
{
|
||||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||||
requested_time = opt6_uint(ia_option, 16, 4);
|
requested_time = opt6_uint(ia_option, 16, 4);
|
||||||
|
struct dhcp_context *dynamic;
|
||||||
if (!address6_available(context, req_addr, tags) &&
|
|
||||||
(!have_config(config, CONFIG_ADDR6) || memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0))
|
if ((dynamic = address6_available(context, req_addr, tags)) || address6_valid(context, req_addr, tags))
|
||||||
{
|
{
|
||||||
if (msg_type == DHCP6REQUEST)
|
if (!dynamic && !(have_config(config, CONFIG_ADDR6) && memcmp(&config->addr6, req_addr, IN6ADDRSZ) == 0))
|
||||||
{
|
{
|
||||||
/* host has a lease, but it's not on the correct link */
|
/* Static range, not configured. */
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6NOTONLINK);
|
put_opt6_short(DHCP6UNSPEC);
|
||||||
put_opt6_string("Not on link");
|
put_opt6_string("Address unavailable");
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
}
|
}
|
||||||
|
else if (lease6_find_by_addr(req_addr, 128, 0) &&
|
||||||
|
!(lease = lease6_find(clid, clid_len, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, req_addr)))
|
||||||
|
{
|
||||||
|
/* Address leased to another DUID/IAID */
|
||||||
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
|
put_opt6_short(DHCP6UNSPEC);
|
||||||
|
put_opt6_string("Address in use");
|
||||||
|
end_opt6(o1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addrp = req_addr;
|
||||||
}
|
}
|
||||||
else if ((lease = lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
else if (msg_type == DHCP6REQUEST)
|
||||||
iaid, req_addr)) &&
|
|
||||||
(clid_len != lease->clid_len ||
|
|
||||||
memcmp(clid, lease->clid, clid_len) != 0))
|
|
||||||
{
|
{
|
||||||
/* Address leased to another DUID */
|
/* requested address not on the correct link */
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6UNSPEC);
|
put_opt6_short(DHCP6NOTONLINK);
|
||||||
put_opt6_string("Address in use");
|
put_opt6_string("Not on link");
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
addrp = req_addr;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -567,9 +575,9 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
|
|||||||
inet_ntop(AF_INET6, &config->addr6, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET6, &config->addr6, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
|
||||||
if (ltmp && ltmp->clid &&
|
if (ltmp && ltmp->clid &&
|
||||||
(ltmp->clid_len != clid_len || memcmp(ltmp->clid, clid, clid_len) != 0))
|
(ltmp->clid_len != clid_len || memcmp(ltmp->clid, clid, clid_len) != 0 || ltmp->hwaddr_type != iaid))
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s#%d"),
|
||||||
daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len));
|
daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len), ltmp->hwaddr_type);
|
||||||
else if (have_config(config, CONFIG_DECLINED) &&
|
else if (have_config(config, CONFIG_DECLINED) &&
|
||||||
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
|
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
|
||||||
|
|||||||
Reference in new issue
Block a user