Compare commits

...
30 Commits
Author SHA1 Message Date
Simon Kelley a21e27bc99 Support DHCP DNS server option if we're not doing DNS. 2013-02-17 16:41:35 +00:00
Simon Kelley b0ff858e78 Fix FTBFS if HAVE_BROKEN_RTC defined. 2013-02-06 09:57:47 +00:00
Simon Kelley 54dae552b1 Fix previous commit. 2013-02-05 17:55:10 +00:00
Simon Kelley 25c4198f7c Fix use-after-free 2013-02-05 14:56:02 +00:00
Simon Kelley 4ead40cf67 Fix use-after-free 2013-02-05 14:51:14 +00:00
Simon Kelley 04a0612e8a Remove dead code. 2013-02-05 14:47:46 +00:00
Simon Kelley aa608c84b4 Fix wrong syntax check. 2013-02-05 14:42:59 +00:00
Simon Kelley 38365ff040 Theoretical memory leak fix. 2013-02-05 14:35:54 +00:00
Simon Kelley 9c4270bcd9 Fix memory leak. 2013-02-04 22:07:57 +00:00
Simon Kelley 46b066565e Don't leak sockets when getsockname fails. 2013-02-04 21:47:59 +00:00
Simon Kelley 4dc9c657ad Memory leak. 2013-02-04 21:43:52 +00:00
Simon Kelley 39595cfe31 Fix memory leak. 2013-02-04 21:40:07 +00:00
Simon Kelley ffa3d7d6a2 Copy-and-paste error 2013-02-04 21:35:43 +00:00
Simon Kelley aa67fe7a8c Catch NULL pointer deref if qdcount == 0 2013-02-04 21:32:34 +00:00
Simon Kelley bb2509fd2c Typo in filter_constructed_dhcp() 2013-02-04 21:25:21 +00:00
Simon Kelley 61744359de Change copyright messages to include 2013. 2013-01-31 14:34:40 +00:00
Simon Kelley 095f62551f Update manpage for --dhcp-authoritative DHCPv6 behaviour. 2013-01-30 11:31:02 +00:00
Simon Kelley e25db1f273 Handle wrong interface for locally-routed packets. 2013-01-29 22:10:26 +00:00
Simon Kelley 79cb46c0e9 Man page typos. 2013-01-23 19:49:21 +00:00
Simon Kelley 22ce550e53 Correct behaviour for TCP queries to allowed address via banned interface. 2013-01-22 13:53:04 +00:00
Simon Kelley 30393100c1 Wildcard IPv6 addresses in --dhcp-host, for constructed ranges. 2013-01-17 16:34:16 +00:00
Simon Kelley 459380965a Fix last commit. 2013-01-15 21:57:42 +00:00
Simon Kelley 21bac1bccd Check IAID as well as CLID for lease identity. 2013-01-14 21:35:05 +00:00
Simon Kelley b1a1b6def5 Tweak DHCP startup logging. 2013-01-11 16:28:50 +00:00
Simon Kelley baeb3adf21 More IPv6 address allocation fixes. 2013-01-10 11:47:38 +00:00
Simon Kelley 39f6a04ca4 Better fix for interfaces without broadcast address on *BSD. 2013-01-09 19:57:47 +00:00
Simon Kelley 37c9ccebd1 DHCPv6 address allocation - same DUID, two IAIDs 2013-01-09 19:51:04 +00:00
Simon Kelley 71c73ac17c Fix crash on startup on Solaris 11 2013-01-08 21:22:24 +00:00
Simon Kelley c6cb7407b3 Don't do AXFR unless auth-sec-servers is set. 2013-01-07 21:55:54 +00:00
Simon Kelley 333b2ceb97 Documentation updates for auth-DNS and constructed dhcp ranges. 2013-01-07 21:46:03 +00:00
35 changed files with 628 additions and 225 deletions

No files matched your search

+34
View File
@@ -1,3 +1,37 @@
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.
Add code to make behaviour for TCP DNS requests that same
as for UDP requests, when a request arrives for an allowed
address, but via a banned interface. This change is only
active on Linux, since the relevant API is missing (AFAIK)
on other platforms. Many thanks to Tomas Hozza for
spotting the problem, and doing invaluable discovery of
the obscure and undocumented API required for the solution.
Don't send the default DHCP option advertising dnsmasq as
the local DNS server if dnsmasq is configured to not act
as DNS server, or it's configured to a non-standard port.
version 2.65
Fix regression which broke forwarding of queries sent via
TCP which are not for A and AAAA and which were directed to
+1 -1
View File
@@ -1,4 +1,4 @@
# dnsmasq is Copyright (c) 2000-2012 Simon Kelley
# dnsmasq is Copyright (c) 2000-2013 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
-4
View File
@@ -255,10 +255,6 @@ int main(int argc, char **argv)
struct ifreq ifr;
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
struct iovec iov;
iov.iov_len = 200;
iov.iov_base = malloc(iov.iov_len);
if (argc < 4 || argc > 5)
{
+1 -1
View File
@@ -1,4 +1,4 @@
dnsmasq is Copyright (c) 2000-2012 Simon Kelley
dnsmasq is Copyright (c) 2000-2013 Simon Kelley
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
+182 -6
View File
@@ -75,6 +75,9 @@ the upstream DNS servers.
.B --max-cache-ttl=<time>
Set a maximum TTL value for entries in the cache.
.TP
.B --auth-ttl=<time>
Set the TTL value returned in answers from the authoritative server.
.TP
.B \-k, --keep-in-foreground
Do not go into the background at startup but otherwise run as
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
.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
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.
.TP
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.
.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
Read the Linux connection track mark associated with incoming DNS
queries and set the same mark value on upstream traffic used to answer
@@ -695,7 +717,13 @@ A single
.B dhcp-host
may contain an IPv4 address or an IPv6 address, or both. IPv6 addresses must be bracketed by square brackets thus:
.B --dhcp-host=laptop,[1234::56]
Note that in IPv6 DHCP, the hardware address is not normally available, so a client must be identified by client-id (called client DUID in IPv6-land) or hostname.
IPv6 addresses may contain only the host-identifier part:
.B --dhcp-host=laptop,[::56]
in which case thay act as wildcards in constructed dhcp ranges, with
the appropriate network part inserted.
Note that in IPv6 DHCP, the hardware address is not normally
available, so a client must be identified by client-id (called client
DUID in IPv6-land) or hostname.
The special option id:* means "ignore any client-id
and use MAC addresses only." This is useful when a client presents a client-id sometimes
@@ -1094,12 +1122,13 @@ create thousands of leases and use lots of memory in the dnsmasq
process.
.TP
.B \-K, --dhcp-authoritative
(IPv4 only) Should be set when dnsmasq is definitely the only DHCP server on a network.
It changes the behaviour from strict RFC compliance so that DHCP requests on
Should be set when dnsmasq is definitely the only DHCP server on a network.
For DHCPv4, it changes the behaviour from strict RFC compliance so that DHCP requests on
unknown leases from unknown hosts are not ignored. This allows new hosts
to get a lease without a tedious timeout under all circumstances. It also
allows dnsmasq to rebuild its lease database without each client needing to
reacquire a lease, if the database is lost.
reacquire a lease, if the database is lost. For DHCPv6 it sets the
priority in replies to 255 (the maximum) instead of 0 (the minimum).
.TP
.B --dhcp-alternate-port[=<server port>[,<client port>]]
(IPv4 only) Change the ports used for DHCP from the default. If this option is
@@ -1671,6 +1700,153 @@ parameter in a BOOTP request is used as a tag,
as is the tag "bootp", allowing some control over the options returned to
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
.PP
0 - Dnsmasq successfully forked into the background, or terminated
+23 -25
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -51,7 +51,7 @@ static int filter_constructed_dhcp(struct auth_zone *zone, int flag, struct all_
#ifdef HAVE_DHCP6
struct dhcp_context *context;
if (flag | F_IPV6)
if (flag & F_IPV6)
for (context = daemon->dhcp6; context; context = context->next)
if ((context->flags & CONTEXT_CONSTRUCTED) &&
is_same_net6(&(addr_u->addr.addr6), &context->start6, context->prefix))
@@ -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)
{
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)
peer_addr->in.sin_port = 0;
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
#ifdef HAVE_IPV6
else
peer_addr->in6.sin6_port = 0;
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
#endif
for (peers = daemon->auth_peers; peers; peers = peers->next)
if (sockaddr_isequal(peer_addr, &peers->addr))
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;
}
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
return 0;
}
soa = 1; /* inhibits auth section */
ns = 1; /* ensure we include NS records! */
axfr = 1;
@@ -472,7 +470,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
}
/* Add auth section */
if (auth)
if (auth && zone)
{
char *authname;
int newoffset, offset = 0;
+6 -3
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -111,7 +111,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
{
int iface_index = if_nametoindex(addrs->ifa_name);
if (iface_index == 0)
if (iface_index == 0 || !addrs->ifa_addr || !addrs->ifa_netmask)
continue;
if (family == AF_INET)
@@ -119,7 +119,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
struct in_addr addr, netmask, broadcast;
addr = ((struct sockaddr_in *) addrs->ifa_addr)->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)))
goto err;
}
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+19 -12
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -91,16 +91,19 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
static void remove_watch(DBusWatch *watch, void *data)
{
struct watch **up, *w;
struct watch **up, *w, *tmp;
for (up = &(daemon->watches), w = daemon->watches; w; w = w->next)
if (w->watch == watch)
{
*up = w->next;
free(w);
}
else
up = &(w->next);
for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
{
tmp = w->next;
if (w->watch == watch)
{
*up = tmp;
free(w);
}
else
up = &(w->next);
}
w = data; /* no warning */
}
@@ -340,9 +343,11 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
}
/* dup the string because it gets modified during parsing */
if (dup)
free(dup);
if (!(dup = str_domain = whine_malloc(strlen(str)+1)))
break;
strcpy(str_domain, str);
/* point to address part of old string for error message */
@@ -400,9 +405,11 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
}
/* dup the string because it gets modified during parsing */
if (dup)
free(dup);
if (!(dup = str_addr = whine_malloc(strlen(str)+1)))
break;
strcpy(str_addr, str);
}
+37 -45
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -679,7 +679,7 @@ void log_context(int family, struct dhcp_context *context)
void *start = &context->start;
void *end = &context->end;
char *n = "", *m = "", *p = daemon->namebuff;
char *template = "", *p = daemon->namebuff;
*p = 0;
@@ -694,67 +694,59 @@ void log_context(int family, struct dhcp_context *context)
end = &context->end6;
}
#endif
if ((context->flags & CONTEXT_DHCP) ||
!(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)))
if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
strcpy(daemon->namebuff, _(", prefix deprecated"));
else
{
if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
strcpy(daemon->namebuff, _(", prefix deprecated"));
else
{
p += sprintf(p, _(", lease time "));
m = p;
prettyprint_time(p, context->lease_time);
p += strlen(p);
}
}
p += sprintf(p, _(", lease time "));
prettyprint_time(p, context->lease_time);
p += strlen(p);
}
#ifdef HAVE_DHCP6
if (context->flags & CONTEXT_CONSTRUCTED)
{
char ifrn_name[IFNAMSIZ];
if (indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, context->if_index, ifrn_name))
{
n = p;
p += sprintf(p, ", constructed for %s", ifrn_name);
}
}
if (context->flags & CONTEXT_TEMPLATE)
{
n = p;
p += sprintf(p, ", template for %s%s", context->template_interface,
(context->flags & CONTEXT_WILDCARD) ? "*" : "");
}
{
char ifrn_name[IFNAMSIZ];
template = p;
p += sprintf(p, ", ");
if (indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, context->if_index, ifrn_name))
sprintf(p, "constructed for %s", ifrn_name);
}
else if (context->flags & CONTEXT_TEMPLATE)
{
template = p;
p += sprintf(p, ", ");
sprintf(p, "template for %s%s", context->template_interface,
(context->flags & CONTEXT_WILDCARD) ? "*" : "");
}
#endif
if ((context->flags & CONTEXT_DHCP) || family == AF_INET)
{
inet_ntop(family, start, daemon->dhcp_buff, 256);
inet_ntop(family, end, daemon->dhcp_buff3, 256);
my_syslog(MS_DHCP | LOG_INFO,
(context->flags & CONTEXT_RA_STATELESS) ?
_("%s stateless on %s%.0s%.0s") :
_("%s stateless on %s%.0s%.0s%s") :
(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) ?
_("%s, proxy on subnet %.0s%s%.0s") :
_("%s, IP range %s -- %s%s"),
_("%s, proxy on subnet %.0s%s%.0s%.0s") :
_("%s, IP range %s -- %s%s%.0s"),
(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
if (context->flags & CONTEXT_RA_NAME)
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"),
daemon->addrbuff, n);
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"), daemon->addrbuff, template);
if (context->flags & CONTEXT_RA)
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s%s"),
daemon->addrbuff,
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? "" : ", prefix valid ",
(context->flags & (CONTEXT_CONSTRUCTED | CONTEXT_TEMPLATE)) ? n : m);
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"), daemon->addrbuff, template);
#endif
}
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+38 -22
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -211,7 +211,8 @@ static int complete_context6(struct in6_addr *local, int prefix,
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 &&
is_same_net6(local, &context->start6, 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;
}
/* can dynamically allocate addr */
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids)
@@ -352,6 +354,21 @@ struct dhcp_context *address6_available(struct dhcp_context *context,
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 in6_addr *taddr,
struct dhcp_netid *netids)
@@ -366,21 +383,12 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
struct dhcp_context *tmp;
if (!(tmp = address6_available(context, taddr, netids)))
{
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_STATIC))
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;
}
if (!(tmp = address6_available(context, taddr, netids)) &&
!(tmp = address6_valid(context, taddr, netids)))
for (tmp = context; tmp; tmp = tmp->current)
if (match_netid(tmp->filter, netids, 1) &&
is_same_net6(taddr, &tmp->start6, tmp->prefix))
break;
/* Only one context allowed now */
if (tmp)
@@ -391,11 +399,19 @@ struct dhcp_context *narrow_context6(struct dhcp_context *context,
static int is_config_in_context6(struct dhcp_context *context, struct dhcp_config *config)
{
if (!context) /* called via find_config() from lease_update_from_configs() */
return 1;
/* expand wildcard on contructed contexts */
if ((config->flags & CONFIG_WILDCARD) &&
(context->flags & CONTEXT_CONSTRUCTED))
{
u64 addrpart = addr6part(&config->addr6);
config->addr6 = context->start6;
setaddr6part(&config->addr6, addrpart);
return 1;
}
if (!(config->flags & CONFIG_ADDR6) || is_addr_in_context6(context, &config->addr6))
return 1;
return 0;
}
@@ -604,10 +620,10 @@ void dhcp_construct_contexts(time_t now)
if (context->flags & CONTEXT_GC)
{
*up = context->next;
free(context);
param.newone = 1; /* include deletion */
if (context->flags & CONTEXT_RA_NAME)
param.newname = 1;
param.newname = 1;
free(context);
}
else
up = &context->next;
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+61 -23
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -158,10 +158,10 @@ int main (int argc, char **argv)
now = dnsmasq_time();
/* Create a serial at startup is not configured. */
/* Create a serial at startup if not configured. */
if (daemon->authinterface && daemon->soa_sn == 0)
#ifdef HAVE_BROKEN_RTC
die(_("zone serial must be configured in --auth-soa"));
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
#else
daemon->soa_sn = now;
#endif
@@ -1337,7 +1337,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
{
int confd;
int confd, client_ok = 1;
struct irec *iface = NULL;
pid_t p;
union mysockaddr tcp_addr;
@@ -1345,28 +1345,66 @@ static void check_dns_listeners(fd_set *set, time_t now)
while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1 ||
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
if (confd == -1)
continue;
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */
else
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
{
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces())
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
close(confd);
continue;
}
if (!iface && !(option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND)))
if (option_bool(OPT_NOWILD))
iface = listener->iface; /* May be NULL */
else
{
int if_index;
char intr_name[IF_NAMESIZE];
/* In full wildcard mode, need to refresh interface list.
This happens automagically in CLEVERBIND */
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
/* if we can find the arrival interface, check it's one that's allowed */
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
indextoname(listener->tcpfd, if_index, intr_name))
{
struct all_addr addr;
addr.addr.addr4 = tcp_addr.in.sin_addr;
#ifdef HAVE_IPV6
if (tcp_addr.sa.sa_family == AF_INET6)
addr.addr.addr6 = tcp_addr.in6.sin6_addr;
#endif
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == if_index)
break;
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
client_ok = 0;
}
if (option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */
else
{
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
if (!iface)
client_ok = 0;
}
}
if (!client_ok)
{
shutdown(confd, SHUT_RDWR);
close(confd);
+8 -2
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define COPYRIGHT "Copyright (c) 2000-2012 Simon Kelley"
#define COPYRIGHT "Copyright (c) 2000-2013 Simon Kelley"
#ifndef NO_LARGEFILE
/* Ensure we can use files >2GB (log files may grow this big) */
@@ -593,6 +593,7 @@ struct dhcp_config {
#define CONFIG_DECLINED 1024 /* address declined by client */
#define CONFIG_BANK 2048 /* from dhcp hosts file */
#define CONFIG_ADDR6 4096
#define CONFIG_WILDCARD 8192
struct dhcp_opt {
int opt, len, flags;
@@ -1001,7 +1002,9 @@ void create_wildcard_listeners(void);
void create_bound_listeners(int die);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
int fix_fd(int fd);
int tcp_interface(int fd, int af);
struct in_addr get_ifaddr(char *intr);
#ifdef HAVE_IPV6
int set_ipv6pktinfo(int fd);
@@ -1149,6 +1152,9 @@ int is_addr_in_context6(struct dhcp_context *context, struct in6_addr *addr);
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
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 in6_addr *taddr,
struct dhcp_netid *netids);
+11 -4
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -763,10 +763,17 @@ void receive_query(struct listener *listen, time_t now)
/* enforce available interface configuration */
if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
if (!indextoname(listen->fd, if_index, ifr.ifr_name))
return;
if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name))
return;
}
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
{
struct irec *iface;
@@ -780,7 +787,7 @@ void receive_query(struct listener *listen, time_t now)
break;
/* interface may be new */
if (!iface)
if (!iface && !option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
for (iface = daemon->interfaces; iface; iface = iface->next)
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+116 -9
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -170,7 +170,40 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
return ret;
}
/* Fix for problem that the kernel sometimes reports the loopback inerface as the
arrival interface when a packet originates locally, even when sent to address of
an interface other than the loopback. Accept packet if it arrived via a loopback
interface, even when we're not accepting packets that way, as long as the destination
address is one we're believing. Interface list must be up-to-date before calling. */
int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
{
struct ifreq ifr;
struct irec *iface;
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
ifr.ifr_flags & IFF_LOOPBACK)
{
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->addr.sa.sa_family == family)
{
if (family == AF_INET)
{
if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
return 1;
}
#ifdef HAVE_IPV6
else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
return 1;
#endif
}
}
return 0;
}
static int iface_allowed(struct irec **irecp, int if_index,
union mysockaddr *addr, struct in_addr netmask, int dad)
{
@@ -225,14 +258,17 @@ static int iface_allowed(struct irec **irecp, int if_index,
if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
break;
if (!lo &&
(lo = whine_malloc(sizeof(struct iname))) &&
(lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
if (!lo && (lo = whine_malloc(sizeof(struct iname))))
{
strcpy(lo->name, ifr.ifr_name);
lo->used = 1;
lo->next = daemon->if_names;
daemon->if_names = lo;
if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
{
strcpy(lo->name, ifr.ifr_name);
lo->used = 1;
lo->next = daemon->if_names;
daemon->if_names = lo;
}
else
free(lo);
}
}
@@ -459,6 +495,77 @@ int set_ipv6pktinfo(int fd)
return 0;
}
#endif
/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
int tcp_interface(int fd, int af)
{
int if_index = 0;
#ifdef HAVE_LINUX_NETWORK
int opt = 1;
struct cmsghdr *cmptr;
struct msghdr msg;
/* use mshdr do that the CMSDG_* macros are available */
msg.msg_control = daemon->packet;
msg.msg_controllen = daemon->packet_buff_sz;
/* we overwrote the buffer... */
daemon->srv_save = NULL;
if (af == AF_INET)
{
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
union {
unsigned char *c;
struct in_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex;
}
}
#ifdef HAVE_IPV6
else
{
/* Only the RFC-2292 API has the ability to find the interface for TCP connections,
it was removed in RFC-3542 !!!!
Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
uses the old ABI, and should work with pre- and post-3542 kernel headers */
#ifdef IPV6_2292PKTOPTIONS
# define PKTOPTIONS IPV6_2292PKTOPTIONS
#else
# define PKTOPTIONS IPV6_PKTOPTIONS
#endif
if (set_ipv6pktinfo(fd) &&
getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
{
union {
unsigned char *c;
struct in6_pktinfo *p;
} p;
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi6_ifindex;
}
}
}
#endif /* IPV6 */
#endif /* Linux */
return if_index;
}
static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
{
+17 -8
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -392,7 +392,7 @@ static struct {
{ 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 },
{ 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_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 },
@@ -1369,14 +1369,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
strcat(path, "/");
strcat(path, ent->d_name);
/* files must be readable */
if (stat(path, &buf) == -1)
die(_("cannot access %s: %s"), path, EC_FILE);
/* only reg files allowed. */
if (!S_ISREG(buf.st_mode))
continue;
/* files must be readable */
one_file(path, 0);
/* only reg files allowed. */
if (S_ISREG(buf.st_mode))
one_file(path, 0);
free(path);
}
@@ -2378,7 +2378,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (!(*cp >= '0' && *cp <= '9'))
break;
if (!cp || (leasepos+1 < k))
if (*cp || (leasepos+1 < k))
ret_err(_("bad dhcp-range"));
new->lease_time = atoi(a[leasepos]) * fac;
@@ -2468,6 +2468,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (!inet_pton(AF_INET6, arg, &new->addr6))
ret_err(_("bad IPv6 address"));
for (i= 0; i < 8; i++)
if (new->addr6.s6_addr[i] != 0)
break;
/* set WILDCARD if network part all zeros */
if (i == 8)
new->flags |= CONFIG_WILDCARD;
new->flags |= CONFIG_ADDR6;
}
@@ -2628,6 +2636,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else
{
new->set = NULL;
free(newtag);
break;
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+4 -3
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -1739,7 +1739,7 @@ static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, i
if (overload[2] & 2)
{
p = dhcp_skip_opts(mess->sname);
if (p + len + 3 >= mess->sname + sizeof(mess->file))
if (p + len + 3 >= mess->sname + sizeof(mess->sname))
p = NULL;
}
}
@@ -2234,7 +2234,8 @@ static void do_options(struct dhcp_context *context,
!option_find2(OPTION_ROUTER))
option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
if (in_list(req_options, OPTION_DNSSERVER) &&
if (daemon->port == NAMESERVER_PORT &&
in_list(req_options, OPTION_DNSSERVER) &&
!option_find2(OPTION_DNSSERVER))
option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
}
+41 -33
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -82,18 +82,20 @@ static int dhcp6_maybe_relay(struct in6_addr *link_address, struct dhcp_netid **
{
struct dhcp_context *c;
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)
{
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);
requested_time = opt6_uint(ia_option, 16, 4);
if (!address6_available(context, req_addr, tags) &&
(!have_config(config, CONFIG_ADDR6) || memcmp(&config->addr6, req_addr, IN6ADDRSZ) != 0))
struct dhcp_context *dynamic;
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);
put_opt6_short(DHCP6NOTONLINK);
put_opt6_string("Not on link");
put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Address unavailable");
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,
iaid, req_addr)) &&
(clid_len != lease->clid_len ||
memcmp(clid, lease->clid, clid_len) != 0))
else if (msg_type == DHCP6REQUEST)
{
/* Address leased to another DUID */
/* requested address not on the correct link */
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6UNSPEC);
put_opt6_string("Address in use");
put_opt6_short(DHCP6NOTONLINK);
put_opt6_string("Not on link");
end_opt6(o1);
}
else
addrp = req_addr;
}
}
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);
if (ltmp && ltmp->clid &&
(ltmp->clid_len != clid_len || memcmp(ltmp->clid, clid, clid_len) != 0))
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len));
(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#%d"),
daemon->addrbuff, print_mac(daemon->namebuff, ltmp->clid, ltmp->clid_len), ltmp->hwaddr_type);
else if (have_config(config, CONFIG_DECLINED) &&
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
@@ -1257,7 +1265,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
end_opt6(o);
}
if (!done_dns &&
if (daemon->port == NAMESERVER_PORT && !done_dns &&
(!IN6_IS_ADDR_UNSPECIFIED(&context->local6) ||
!IN6_IS_ADDR_UNSPECIFIED(fallback)))
{
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
+12 -7
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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
@@ -61,6 +61,7 @@ void tftp_request(struct listener *listen, time_t now)
char *name = NULL;
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct all_addr addra;
union {
struct cmsghdr align; /* this ensures alignment */
@@ -189,18 +190,22 @@ void tftp_request(struct listener *listen, time_t now)
return;
name = namebuff;
addra.addr.addr4 = addr.in.sin_addr;
#ifdef HAVE_IPV6
if (listen->family == AF_INET6)
addra.addr.addr6 = addr.in6.sin6_addr;
#endif
if (!iface_check(listen->family, &addra, name, NULL))
{
if (!iface_check(AF_INET6, (struct all_addr *)&addr.in6.sin6_addr, name, NULL))
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces();
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name))
return;
}
else
#endif
if (!iface_check(AF_INET, (struct all_addr *)&addr.in.sin_addr, name, NULL))
return;
#ifdef HAVE_DHCP
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
+1 -1
View File
@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
/* dnsmasq is Copyright (c) 2000-2013 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