Compare commits

...
22 Commits
Author SHA1 Message Date
Simon Kelley 00238fb019 indentation fix. 2013-12-18 13:24:12 +00:00
Simon Kelley 74e6b52011 Typo in contributor name. Sorry. 2013-12-17 21:33:53 +00:00
Simon Kelley 875b8160f6 Remove unused code. 2013-12-17 17:40:32 +00:00
Simon Kelley 76ff440ebe Ignore ",," in dhcp-host, rather than treating it as ",0," 2013-12-17 16:29:14 +00:00
Simon Kelley 8db957dfbf Fix endless loop with some bogu-nxdomain. Another F_CONFIG botch. 2013-12-17 15:47:10 +00:00
Simon Kelley 1ee9be4c3f Implement dynamic interface discovery on *BSD 2013-12-09 16:50:19 +00:00
Simon Kelley 56ad6c9be1 Bump debian version. 2013-12-08 15:58:29 +00:00
Jan Psota fa04c83d86 Update Polish translation. 2013-12-08 15:43:03 +00:00
Vladislav Grishenko 4c82efc5ac Relax rules in prefix length in (IPv6) dhcp-range. 2013-12-03 16:05:30 +00:00
Simon Kelley 5f45d6a715 Update Debian changelog. 2013-12-03 13:43:56 +00:00
Simon Kelley 2329bef5ba Check arrival interface of IPv6 requests, even in --bind-interfaces. 2013-12-03 13:41:16 +00:00
Simon Kelley 62ab3ccd3d Only set scope_id in addresses to bind() for linklocal addresses.
FreeBSD complains otherwise.
2013-12-03 11:53:53 +00:00
Matthias Andree 71aaa5a791 Fix previous errno saving fix. 2013-12-03 11:20:45 +00:00
Simon Kelley 08619211f8 Garbage collect listening sockets when their address is deleted.
In --bind-dynamic mode, stop listening on an address when it's
removed from an interface. 6rd and 6to4 tunnels can go through
lots of addresses.
2013-12-02 14:43:48 +00:00
Simon Kelley 3dffbc3ebf Don't overwrite errno before generating message. 2013-12-02 13:22:37 +00:00
Simon Kelley 0d6eb134f5 Do immediate RA when a prefix goes from old->current. 2013-11-26 13:30:12 +00:00
Vladislav Grishenko 50db3492e2 Fix compiler warning. 2013-11-26 11:09:31 +00:00
Vladislav Grishenko 3b19596122 Fix compiler warnings. 2013-11-26 11:08:21 +00:00
Vladislav Grishenko d082faf3e4 Fix compiler warning. 2013-11-26 11:04:24 +00:00
Vladislav Grishenko 99e8891f85 Fix compiler warning. 2013-11-26 11:02:29 +00:00
Simon Kelley 532066ee2d Add missing malloc() return-code check. 2013-11-26 10:14:47 +00:00
Simon Kelley 254390644a Segfault with some CNAMEs. Also memory leak on reload of /etc/hosts. 2013-11-25 21:14:51 +00:00
20 changed files with 367 additions and 165 deletions

No files matched your search

+28 -1
View File
@@ -1,3 +1,13 @@
version 2.69
Implement dynamic interface discovery on *BSD. This allows
the contructor: syntax to be used in dhcp-range for DHCPv6
on the BSD platform. Thanks to Matthias Andree for
valuable research on how to implement this.
Fix infinite loop associated with some --bogus-nxdomain
configs. Thanks fogobogo for the bug report.
version 2.68
Use random addresses for DHCPv6 temporary address
allocations, instead of algorithmically determined stable
@@ -32,7 +42,24 @@ version 2.68
the prefix is deleted (rather than replaced), it doesn't
get advertised with zero preferred time. Thanks to Tsachi
for the bug report.
Fix segfault with some locally configured CNAMEs. Thanks
to Andrew Childs for spotting the problem.
Fix memory leak on re-reading /etc/hosts and friends,
introduced in 2.67.
Check the arrival interface of incoming DNS and TFTP
requests via IPv6, even in --bind-interfaces mode. This
isn't possible for IPv4 and can generate scary warnings,
but as it's always possible for IPv6 (the API always
exists) then we should do it always.
Tweak the rules on prefix-lengths in --dhcp-range for
IPv6. The new rule is that the specified prefix length
must be larger than or equal to the prefix length of the
corresponding address on the local interface.
version 2.67
Fix crash if upstream server returns SERVFAIL when
+6
View File
@@ -1,3 +1,9 @@
dnsmasq (2.68-1) unstable; urgency=low
* New upstream. (closes: #730553)
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 8 Dec 2013 15:57:32 +0000
dnsmasq (2.67-1) unstable; urgency=low
* New upstream.
+2 -1
View File
@@ -673,7 +673,8 @@ always optional. It is always
allowed to have more than one dhcp-range in a single subnet.
For IPv6, the parameters are slightly different: instead of netmask
and broadcast address, there is an optional prefix length. If not
and broadcast address, there is an optional prefix length which must
be equal to or larger then the prefix length on the local interface. If not
given, this defaults to 64. Unlike the IPv4 case, the prefix length is not
automatically derived from the interface configuration. The mimimum
size of the prefix length is 64.
+18 -20
View File
@@ -10,15 +10,15 @@ msgstr ""
"Project-Id-Version: pl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-10 20:57+0100\n"
"PO-Revision-Date: 2013-10-01 23:23+0200\n"
"PO-Revision-Date: 2013-12-04 01:34+0100\n"
"Last-Translator: Jan Psota <jasiupsota@gmail.com>\n"
"Language-Team: polski <>\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bits\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
"X-Generator: Gtranslator 2.91.6\n"
"X-Generator: Poedit 1.5.5\n"
"X-Language: pl_PL\n"
#: cache.c:821
@@ -76,9 +76,9 @@ msgid "queries forwarded %u, queries answered locally %u"
msgstr "%u zapytań przesłanych dalej, %u odpowiedzi udzielonych samodzielnie"
#: cache.c:1165
#, fuzzy, c-format
#, c-format
msgid "queries for authoritative zones %u"
msgstr "Określenie TTL dla odpowiedzi autorytatywnych"
msgstr "zapytań do stref autorytatywnych %u"
#: cache.c:1188
#, c-format
@@ -563,9 +563,8 @@ msgid "Add requestor's MAC address to forwarded DNS queries."
msgstr "Przekazywanie MAC-adresu komputera pytającego w ruchu wychodzącym DNS."
#: option.c:409
#, fuzzy
msgid "Add requestor's IP subnet to forwarded DNS queries."
msgstr "Przekazywanie MAC-adresu komputera pytającego w ruchu wychodzącym DNS."
msgstr "Zamieszczanie adresu IP pytającego w przekazywanych zapytaniach DNS."
#: option.c:410
msgid "Proxy DNSSEC validation results from upstream nameservers."
@@ -632,9 +631,8 @@ msgid "Specify ipsets to which matching domains should be added"
msgstr "Wyszczególnienie ipset-ów, do których będą dopisywane adresy IP leżące we wskazanych domenach"
#: option.c:426
#, fuzzy
msgid "Specify a domain and address range for synthesised names"
msgstr "Określenie domeny i zakresu adresów dla tworzonych nazw"
msgstr "Wskazanie domeny i zakresu adresów dla generowanych nazw"
#: option.c:428
msgid "Specify DHCPv6 prefix class"
@@ -642,19 +640,19 @@ msgstr "Określenie prefiksu klasy DHCPv6"
#: option.c:430
msgid "Set priority, resend-interval and router-lifetime"
msgstr ""
msgstr "Ustawianie priorytetu, okresu rozsyłania oraz czasu życia rutera (RA)."
#: option.c:431
msgid "Do not log routine DHCP."
msgstr ""
msgstr "Wyłączenie logowania zwyczajnego DHCP."
#: option.c:432
msgid "Do not log routine DHCPv6."
msgstr ""
msgstr "Wyłączenie logowania zwyczajnego DHCPv6."
#: option.c:433
msgid "Do not log RA."
msgstr ""
msgstr "Wyłączenie logowania RA."
#: option.c:618
#, c-format
@@ -852,7 +850,7 @@ msgstr "zły dhcp-relay"
#: option.c:3304
msgid "bad RA-params"
msgstr ""
msgstr "nieprawidłowe argumenty RA"
#: option.c:3313
msgid "bad DUID"
@@ -1033,7 +1031,7 @@ msgstr "wysyłanie pakietu nie powiodło się: %s"
#: forward.c:493
msgid "discarding DNS reply: subnet option mismatch"
msgstr ""
msgstr "odrzucam odpowiedź DNS: nie zgadza się specyfikacja podsieci"
#: forward.c:511
#, c-format
@@ -1058,16 +1056,16 @@ msgstr "nie udało się otworzyć gniazda %s: %s"
#: network.c:947
#, c-format
msgid "LOUD WARNING: listening on %s may accept requests via interfaces other than %s"
msgstr ""
msgstr "UWAGA: nasłuchiwanie na %s może przyjmować żądania przychodzące przez interfejsy inne niż %s"
#: network.c:953
msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"
msgstr ""
msgstr "UWAGA: zastosowanie --bind-dynamic zamiast --bind-interfaces daje ochronę przed atakami wzmocnienia DNS"
#: network.c:962
#, fuzzy, c-format
#, c-format
msgid "warning: no addresses found for interface %s"
msgstr "używam adresów lokalnych tylko dla %s %s"
msgstr "uwaga: nie znaleziono adresu interfejsu %s"
#: network.c:1020
#, c-format
@@ -1257,7 +1255,7 @@ msgstr "anonsowanie rutera IPv6 włączone"
#: dnsmasq.c:685
#, c-format
msgid "DHCP, sockets bound exclusively to interface %s"
msgstr ""
msgstr "DHCP, gniazda dowiązane na wyłączność interfejsowi %s"
#: dnsmasq.c:702
msgid "root is "
+102 -4
View File
@@ -19,9 +19,9 @@
#if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
#include <ifaddrs.h>
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/if_ether.h>
@@ -29,7 +29,9 @@
# include <net/if_var.h>
#endif
#include <netinet/in_var.h>
#include <netinet6/in6_var.h>
#ifdef HAVE_IPV6
# include <netinet6/in6_var.h>
#endif
#ifndef SA_SIZE
#define SA_SIZE(sa) \
@@ -38,6 +40,13 @@
1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
#endif
#ifdef HAVE_BSD_NETWORK
static int del_family = 0;
static struct all_addr del_addr;
#endif
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
int arp_enumerate(void *parm, int (*callback)())
{
int mib[6];
@@ -88,7 +97,7 @@ int arp_enumerate(void *parm, int (*callback)())
return 1;
}
#endif
#endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */
int iface_enumerate(int family, void *parm, int (*callback)())
@@ -129,6 +138,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;
#ifdef HAVE_BSD_NETWORK
if (del_family == AF_INET && del_addr.addr.addr4.s_addr == addr.s_addr)
continue;
#endif
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
if (addrs->ifa_broadaddr)
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
@@ -146,6 +159,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
int i, j, prefix = 0;
u32 valid = 0xffffffff, preferred = 0xffffffff;
int flags = 0;
#ifdef HAVE_BSD_NETWORK
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr.addr6, addr))
continue;
#endif
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
struct in6_ifreq ifr6;
@@ -226,7 +243,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
return ret;
}
#endif
#endif /* defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) */
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
@@ -345,6 +362,87 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
}
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
#ifdef HAVE_BSD_NETWORK
void route_init(void)
{
/* AF_UNSPEC: all addr families */
daemon->routefd = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if (daemon->routefd == -1 || !fix_fd(daemon->routefd))
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
}
void route_sock(time_t now)
{
struct if_msghdr *msg;
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
if (rc < 4)
return;
msg = (struct if_msghdr *)daemon->packet;
if (rc < msg->ifm_msglen)
return;
if (msg->ifm_version != RTM_VERSION)
{
static int warned = 0;
if (!warned)
{
my_syslog(LOG_WARNING, _("Unknown protocol version from route socket"));
warned = 1;
}
}
else if (msg->ifm_type == RTM_NEWADDR)
{
del_family = 0;
newaddress(now);
}
else if (msg->ifm_type == RTM_DELADDR)
{
/* There's a race in the kernel, such that if we run iface_enumerate() immediately
we get a DELADDR event, the deleted address still appears. Here we store the deleted address
in a static variable, and omit it from the set returned by iface_enumerate() */
int mask = ((struct ifa_msghdr *)msg)->ifam_addrs;
int maskvec[] = { RTA_DST, RTA_GATEWAY, RTA_NETMASK, RTA_GENMASK,
RTA_IFP, RTA_IFA, RTA_AUTHOR, RTA_BRD };
int of;
unsigned int i;
for (i = 0, of = sizeof(struct ifa_msghdr); of < rc && i < sizeof(maskvec)/sizeof(maskvec[0]); i++)
if (mask & maskvec[i])
{
struct sockaddr *sa = (struct sockaddr *)((char *)msg + of);
size_t diff = (sa->sa_len != 0) ? sa->sa_len : sizeof(long);
if (maskvec[i] == RTA_IFA)
{
del_family = sa->sa_family;
if (del_family == AF_INET)
del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
#ifdef HAVE_IPV6
else if (del_family == AF_INET6)
del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
#endif
else
del_family = 0;
}
of += diff;
/* round up as needed */
if (diff & (sizeof(long) - 1))
of += sizeof(long) - (diff & (sizeof(long) - 1));
}
newaddress(now);
}
}
#endif /* HAVE_BSD_NETWORK */
+17 -17
View File
@@ -320,7 +320,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -354,13 +354,13 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
if (is_expired(now, crecp))
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
}
}
else if (!(crecp->flags & (F_HOSTS | F_DHCP)) &&
else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
(flags & crecp->flags & F_REVERSE) &&
(flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
@@ -558,7 +558,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
(crecp->flags & prot) &&
hostname_isequal(cache_get_name(crecp), name))
{
if (crecp->flags & (F_HOSTS | F_DHCP))
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
{
*chainp = crecp;
chainp = &crecp->next;
@@ -599,7 +599,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
{
/* expired entry, free it */
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -649,7 +649,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
if ((crecp->flags & prot) &&
memcmp(&crecp->addr.addr, addr, addrlen) == 0)
{
if (crecp->flags & (F_HOSTS | F_DHCP))
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
{
*chainp = crecp;
chainp = &crecp->next;
@@ -665,7 +665,7 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
else
{
*up = crecp->hash_next;
if (!(crecp->flags & (F_HOSTS | F_DHCP)))
if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
{
cache_unlink(crecp);
cache_free(crecp);
@@ -923,7 +923,7 @@ void cache_reload(void)
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
{
tmp = cache->hash_next;
if (cache->flags & F_HOSTS)
if (cache->flags & (F_HOSTS | F_CONFIG))
{
*up = cache->hash_next;
free(cache);
@@ -945,15 +945,15 @@ void cache_reload(void)
/* Add CNAMEs to interface_names to the cache */
for (a = daemon->cnames; a; a = a->next)
for (intr = daemon->int_names; intr; intr = intr->next)
if (hostname_isequal(a->target, intr->name))
if (hostname_isequal(a->target, intr->name) &&
((cache = whine_malloc(sizeof(struct crec)))))
{
struct crec *aliasc = safe_malloc(sizeof(struct crec));
aliasc->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
aliasc->name.namep = a->alias;
aliasc->addr.cname.target.int_name = intr;
aliasc->addr.cname.uid = -1;
cache_hash(aliasc);
add_hosts_cname(aliasc); /* handle chains */
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
cache->name.namep = a->alias;
cache->addr.cname.target.int_name = intr;
cache->addr.cname.uid = -1;
cache_hash(cache);
add_hosts_cname(cache); /* handle chains */
}
/* borrow the packet buffer for a temporary by-address hash */
@@ -1083,7 +1083,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
{
/* check all addresses associated with name */
if (crec->flags & F_HOSTS)
if (crec->flags & (F_HOSTS | F_CONFIG))
{
if (crec->flags & F_CNAME)
my_syslog(MS_DHCP | LOG_WARNING,
+7 -7
View File
@@ -399,13 +399,13 @@ void dhcp_update_configs(struct dhcp_config *configs)
if (cache_find_by_name(crec, config->hostname, 0, cacheflags))
{
/* use primary (first) address */
while (crec && !(crec->flags & F_REVERSE))
crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
if (!crec)
continue; /* should be never */
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
config->hostname, daemon->addrbuff);
while (crec && !(crec->flags & F_REVERSE))
crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
if (!crec)
continue; /* should be never */
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
config->hostname, daemon->addrbuff);
}
if (prot == AF_INET &&
+8 -8
View File
@@ -330,9 +330,9 @@ static int complete_context6(struct in6_addr *local, int prefix,
{
if ((context->flags & CONTEXT_DHCP) &&
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
@@ -631,9 +631,9 @@ static int construct_worker(struct in6_addr *local, int prefix,
if (!(template->flags & CONTEXT_TEMPLATE))
{
/* non-template entries, just fill in interface and local addresses */
if (prefix == template->prefix &&
is_same_net6(local, &template->start6, prefix) &&
is_same_net6(local, &template->end6, prefix))
if (prefix <= template->prefix &&
is_same_net6(local, &template->start6, template->prefix) &&
is_same_net6(local, &template->end6, template->prefix))
{
template->if_index = if_index;
template->local6 = *local;
@@ -641,7 +641,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
}
else if (wildcard_match(template->template_interface, ifrn_name) &&
template->prefix == prefix)
template->prefix >= prefix)
{
start6 = *local;
setaddr6part(&start6, addr6part(&template->start6));
@@ -661,6 +661,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
log_context(AF_INET6, context);
/* fast RAs for a while */
ra_start_unsolicted(param->now, context);
param->newone = 1;
/* Add address to name again */
if (context->flags & CONTEXT_RA_NAME)
param->newname = 1;
@@ -719,7 +720,6 @@ void dhcp_construct_contexts(time_t now)
if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
{
if ((context->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) ||
option_bool(OPT_RA))
{
+16 -8
View File
@@ -182,7 +182,7 @@ int main (int argc, char **argv)
daemon->doing_dhcp6 = 1;
if (context->flags & CONTEXT_RA)
daemon->doing_ra = 1;
#ifndef HAVE_LINUX_NETWORK
#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
if (context->flags & CONTEXT_TEMPLATE)
die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
#endif
@@ -220,13 +220,15 @@ int main (int argc, char **argv)
ipset_init();
#endif
#ifdef HAVE_LINUX_NETWORK
#if defined(HAVE_LINUX_NETWORK)
netlink_init();
if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
#elif defined(HAVE_BSD_NETWORK)
route_init();
#endif
if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
@@ -808,11 +810,14 @@ int main (int argc, char **argv)
}
#endif
#ifdef HAVE_LINUX_NETWORK
#if defined(HAVE_LINUX_NETWORK)
FD_SET(daemon->netlinkfd, &rset);
bump_maxfd(daemon->netlinkfd, &maxfd);
#elif defined(HAVE_BSD_NETWORK)
FD_SET(daemon->routefd, &rset);
bump_maxfd(daemon->routefd, &maxfd);
#endif
FD_SET(piperead, &rset);
bump_maxfd(piperead, &maxfd);
@@ -867,9 +872,12 @@ int main (int argc, char **argv)
warn_bound_listeners();
}
#ifdef HAVE_LINUX_NETWORK
#if defined(HAVE_LINUX_NETWORK)
if (FD_ISSET(daemon->netlinkfd, &rset))
netlink_multicast(now);
#elif defined(HAVE_BSD_NETWORK)
if (FD_ISSET(daemon->routefd, &rset))
route_sock(now);
#endif
/* Check for changes to resolv files once per second max. */
+9 -3
View File
@@ -459,7 +459,7 @@ struct ipsets {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done;
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found;
char *name;
struct irec *next;
};
@@ -561,7 +561,7 @@ struct dhcp_lease {
struct in6_addr addr6;
int iaid;
struct slaac_address {
struct in6_addr addr, local;
struct in6_addr addr;
time_t ping_time;
int backoff; /* zero -> confirmed */
struct slaac_address *next;
@@ -900,7 +900,7 @@ extern struct daemon {
#if defined(HAVE_LINUX_NETWORK)
int netlinkfd;
#elif defined(HAVE_BSD_NETWORK)
int dhcp_raw_fd, dhcp_icmp_fd;
int dhcp_raw_fd, dhcp_icmp_fd, routefd;
#endif
struct iovec dhcp_packet;
char *dhcp_buff, *dhcp_buff2, *dhcp_buff3;
@@ -1090,6 +1090,10 @@ int set_ipv6pktinfo(int fd);
#ifdef HAVE_DHCP6
void join_multicast(int dienow);
#endif
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)
void newaddress(time_t now);
#endif
/* dhcp.c */
#ifdef HAVE_DHCP
@@ -1177,6 +1181,8 @@ void netlink_multicast(time_t now);
void init_bpf(void);
void send_via_bpf(struct dhcp_packet *mess, size_t len,
struct in_addr iface_addr, struct ifreq *ifr);
void route_init(void);
void route_sock(time_t now);
#endif
/* bpf.c or netlink.c */
+14 -4
View File
@@ -675,8 +675,10 @@ void receive_query(struct listener *listen, time_t now)
struct in_addr netmask, dst_addr_4;
size_t m;
ssize_t n;
int if_index = 0;
int local_auth = 0, auth_dns = 0;
int if_index = 0, auth_dns = 0;
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmptr;
@@ -695,7 +697,13 @@ void receive_query(struct listener *listen, time_t now)
CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
#ifdef HAVE_IPV6
/* Can always get recvd interface for IPv6 */
int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
#else
int check_dst = !option_bool(OPT_NOWILD);
#endif
/* packet buffer overwritten */
daemon->srv_save = NULL;
@@ -738,7 +746,7 @@ void receive_query(struct listener *listen, time_t now)
source_addr.in6.sin6_flowinfo = 0;
#endif
if (!option_bool(OPT_NOWILD))
if (check_dst)
{
struct ifreq ifr;
@@ -916,7 +924,9 @@ unsigned char *tcp_request(int confd, time_t now,
{
size_t size = 0;
int norebind = 0;
#ifdef HAVE_AUTH
int local_auth = 0;
#endif
int checking_disabled, check_subnet;
size_t m;
unsigned short qtype;
+2 -27
View File
@@ -39,7 +39,6 @@ static struct iovec iov;
static u32 netlink_pid;
static int nl_async(struct nlmsghdr *h);
static void nl_newaddress(time_t now);
void netlink_init(void)
{
@@ -203,7 +202,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
/* handle async new interface address arrivals, these have to be done
after we complete as we're not re-entrant */
if (newaddr)
nl_newaddress(dnsmasq_time());
newaddress(dnsmasq_time());
return callback_ok;
}
@@ -351,7 +350,7 @@ void netlink_multicast(time_t now)
fcntl(daemon->netlinkfd, F_SETFL, flags);
if (newaddr)
nl_newaddress(now);
newaddress(now);
}
static int nl_async(struct nlmsghdr *h)
@@ -399,30 +398,6 @@ static int nl_async(struct nlmsghdr *h)
return 0;
}
static void nl_newaddress(time_t now)
{
(void)now;
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
enumerate_interfaces(0);
if (option_bool(OPT_CLEVERBIND))
create_bound_listeners(0);
#ifdef HAVE_DHCP6
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
join_multicast(0);
if (daemon->doing_dhcp6 || daemon->doing_ra)
dhcp_construct_contexts(now);
if (daemon->doing_dhcp6)
lease_find_interfaces(now);
#endif
}
#endif
+99 -37
View File
@@ -252,6 +252,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
struct iname *tmp;
#endif
(void)prefixlen;
if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
return 0;
@@ -318,7 +320,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
{
al->next = zone->subnet;
zone->subnet = al;
al->prefixlen = prefixlen;al->addr.addr.addr6 = addr->in6.sin6_addr;
al->prefixlen = prefixlen;
al->addr.addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6;
}
}
@@ -368,6 +371,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (sockaddr_isequal(&iface->addr, addr))
{
iface->dad = dad;
iface->found = 1; /* for garbage collection */
return 1;
}
@@ -442,6 +446,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
iface->dns_auth = auth_dns;
iface->mtu = mtu;
iface->dad = dad;
iface->found = 1;
iface->done = iface->multicast_done = iface->warned = 0;
iface->index = if_index;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
@@ -479,7 +484,11 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = *local;
addr.in6.sin6_port = htons(daemon->port);
addr.in6.sin6_scope_id = if_index;
/* FreeBSD insists this is zero for non-linklocal addresses */
if (IN6_IS_ADDR_LINKLOCAL(local))
addr.in6.sin6_scope_id = if_index;
else
addr.in6.sin6_scope_id = 0;
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
}
@@ -514,6 +523,7 @@ int enumerate_interfaces(int reset)
int errsave, ret = 1;
struct addrlist *addr, *tmp;
struct interface_name *intname;
struct irec *iface;
#ifdef HAVE_AUTH
struct auth_zone *zone;
#endif
@@ -538,6 +548,10 @@ int enumerate_interfaces(int reset)
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return 0;
/* Mark interfaces for garbage collection */
for (iface = daemon->interfaces; iface; iface = iface->next)
iface->found = 0;
/* remove addresses stored against interface_names */
for (intname = daemon->int_names; intname; intname = intname->next)
{
@@ -584,11 +598,47 @@ int enumerate_interfaces(int reset)
errsave = errno;
close(param.fd);
if (option_bool(OPT_CLEVERBIND))
{
/* Garbage-collect listeners listening on addresses that no longer exist.
Does nothing when not binding interfaces or for listeners on localhost,
since the ->iface field is NULL. Note that this needs the protections
against re-entrancy, hence it's here. It also means there's a possibility,
in OPT_CLEVERBIND mode, that at listener will just disappear after
a call to enumerate_interfaces, this is checked OK on all calls. */
struct listener *l, *tmp, **up;
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
{
tmp = l->next;
if (!l->iface || l->iface->found)
up = &l->next;
else
{
*up = l->next;
/* In case it ever returns */
l->iface->done = 0;
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
}
}
}
errno = errsave;
spare = param.spare;
active = 0;
return ret;
}
@@ -611,7 +661,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if ((fd = socket(family, type, 0)) == -1)
{
int port;
int port, errsav;
char *s;
/* No error if the kernel just doesn't support this IP flavour */
@@ -621,6 +671,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
return -1;
err:
errsav = errno;
port = prettyprint_addr(addr, daemon->addrbuff);
if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
sprintf(daemon->addrbuff, "port %d", port);
@@ -628,7 +679,9 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (fd != -1)
close (fd);
errno = errsav;
if (dienow)
{
/* failure to bind addresses given by --listen-address at this point
@@ -658,9 +711,9 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
if (listen(fd, 5) == -1)
goto err;
}
else if (!option_bool(OPT_NOWILD))
else if (family == AF_INET)
{
if (family == AF_INET)
if (!option_bool(OPT_NOWILD))
{
#if defined(HAVE_LINUX_NETWORK)
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
@@ -671,11 +724,11 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
goto err;
#endif
}
#ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd))
goto err;
#endif
}
#ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd))
goto err;
#endif
return fd;
}
@@ -823,7 +876,8 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
l->family = addr->sa.sa_family;
l->fd = fd;
l->tcpfd = tcpfd;
l->tftpfd = tftpfd;
l->tftpfd = tftpfd;
l->iface = NULL;
}
return l;
@@ -870,7 +924,7 @@ void create_bound_listeners(int dienow)
struct iname *if_tmp;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad &&
if (!iface->done && !iface->dad && iface->found &&
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{
new->iface = iface;
@@ -894,7 +948,6 @@ void create_bound_listeners(int dienow)
if (!if_tmp->used &&
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
{
new->iface = NULL;
new->next = daemon->listeners;
daemon->listeners = new;
}
@@ -908,6 +961,9 @@ void create_bound_listeners(int dienow)
The fix is to use --bind-dynamic, which actually checks the arrival interface too.
Tough if your platform doesn't support this.
Note that checking the arrival interface is supported in the standard IPv6 API and
always done, so we don't warn about any IPv6 addresses here.
*/
void warn_bound_listeners(void)
@@ -918,35 +974,17 @@ void warn_bound_listeners(void)
for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->dns_auth)
{
int warn = 0;
if (iface->addr.sa.sa_family == AF_INET)
{
if (!private_net(iface->addr.in.sin_addr, 1))
{
inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
iface->warned = advice = 1;
my_syslog(LOG_WARNING,
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
daemon->addrbuff, iface->name);
}
}
#ifdef HAVE_IPV6
else
{
if (!IN6_IS_ADDR_LINKLOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_SITELOCAL(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_ULA(&iface->addr.in6.sin6_addr) &&
!IN6_IS_ADDR_LOOPBACK(&iface->addr.in6.sin6_addr))
{
inet_ntop(AF_INET6, &iface->addr.in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
warn = 1;
}
}
#endif
if (warn)
{
iface->warned = advice = 1;
my_syslog(LOG_WARNING,
_("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
daemon->addrbuff, iface->name);
}
}
if (advice)
@@ -1432,7 +1470,31 @@ int reload_servers(char *fname)
return gotone;
}
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)
/* Called when addresses are added or deleted from an interface */
void newaddress(time_t now)
{
(void)now;
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
enumerate_interfaces(0);
if (option_bool(OPT_CLEVERBIND))
create_bound_listeners(0);
#ifdef HAVE_DHCP6
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
join_multicast(0);
if (daemon->doing_dhcp6 || daemon->doing_ra)
dhcp_construct_contexts(now);
if (daemon->doing_dhcp6)
lease_find_interfaces(now);
#endif
}
#endif
+7 -5
View File
@@ -2732,7 +2732,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else
{
char *cp, *lastp = NULL, last = 0;
int fac = 1;
int fac = 1, isdig = 0;
if (strlen(a[j]) > 1)
{
@@ -2763,9 +2763,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
for (cp = a[j]; *cp; cp++)
if (!isdigit((unsigned char)*cp) && *cp != ' ')
if (isdigit((unsigned char)*cp))
isdig = 1;
else if (*cp != ' ')
break;
if (*cp)
{
if (lastp)
@@ -2787,7 +2789,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->domain = strip_hostname(new->hostname);
}
}
else
else if (isdig)
{
new->lease_time = atoi(a[j]) * fac;
/* Leases of a minute or less confuse
@@ -3482,7 +3484,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_RR: /* dns-rr */
{
struct txt_record *new;
size_t len;
size_t len = len;
char *data;
int val;
+14 -14
View File
@@ -430,7 +430,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
else if (!IN6_IS_ADDR_LOOPBACK(local) &&
!IN6_IS_ADDR_MULTICAST(local))
{
int do_prefix = 0;
int real_prefix = 0;
int do_slaac = 0;
int deprecate = 0;
int constructed = 0;
@@ -439,9 +439,9 @@ static int add_prefixes(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
{
context->saved_valid = valid;
@@ -496,7 +496,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
if (!param->first)
context->ra_time = 0;
context->flags |= CONTEXT_RA_DONE;
do_prefix = 1;
real_prefix = context->prefix;
}
param->first = 0;
@@ -523,18 +523,18 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param->link_global = *local;
}
if (do_prefix)
if (real_prefix != 0)
{
struct prefix_opt *opt;
if ((opt = expand(sizeof(struct prefix_opt))))
{
/* zero net part of address */
setaddr6part(local, addr6part(local) & ~((prefix == 64) ? (u64)-1LL : (1LLU << (128 - prefix)) - 1LLU));
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = prefix;
opt->prefix_len = real_prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80;
opt->valid_lifetime = htonl(valid);
@@ -645,9 +645,9 @@ static int iface_search(struct in6_addr *local, int prefix,
for (context = daemon->dhcp6; context; context = context->next)
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix) &&
prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix) &&
context->ra_time != 0 &&
difftime(context->ra_time, param->now) <= 0.0)
{
@@ -670,9 +670,9 @@ static int iface_search(struct in6_addr *local, int prefix,
/* zero timers for other contexts on the same subnet, so they don't timeout
independently */
for (context = context->next; context; context = context->next)
if (prefix == context->prefix &&
is_same_net6(local, &context->start6, prefix) &&
is_same_net6(local, &context->end6, prefix))
if (prefix <= context->prefix &&
is_same_net6(local, &context->start6, context->prefix) &&
is_same_net6(local, &context->end6, context->prefix))
context->ra_time = 0;
return 0; /* found, abort */
+1 -1
View File
@@ -1283,7 +1283,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
/* Found a bogus address. Insert that info here, since there no SOA record
to get the ttl from in the normal processing */
cache_start_insert();
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN);
cache_end_insert();
return 1;
+7 -3
View File
@@ -92,7 +92,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
struct dhcp_netid known_id, iface_id, cpewan_id;
struct dhcp_opt *o;
unsigned char pxe_uuid[17];
unsigned char *oui = NULL, *serial = NULL, *class = NULL;
unsigned char *oui = NULL, *serial = NULL;
#ifdef HAVE_SCRIPT
unsigned char *class = NULL;
#endif
subnet_addr.s_addr = override.s_addr = 0;
@@ -156,8 +159,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
unsigned char *y = option_ptr(opt, offset + elen + 5);
oui = option_find1(x, y, 1, 1);
serial = option_find1(x, y, 2, 1);
class = option_find1(x, y, 3, 1);
#ifdef HAVE_SCRIPT
class = option_find1(x, y, 3, 1);
#endif
/* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
the gateway id back. Note that the device class is optional */
if (oui && serial)
-1
View File
@@ -93,7 +93,6 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
slaac->ping_time = now;
slaac->backoff = 1;
slaac->addr = addr;
slaac->local = context->local6;
/* Do RA's to prod it */
ra_start_unsolicted(now, context);
}
+9 -3
View File
@@ -60,7 +60,12 @@ void tftp_request(struct listener *listen, time_t now)
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
struct all_addr addra;
#ifdef HAVE_IPV6
/* Can always get recvd interface for IPv6 */
int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
#else
int check_dest = !option_bool(OPT_NOWILD);
#endif
union {
struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6
@@ -91,8 +96,9 @@ void tftp_request(struct listener *listen, time_t now)
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
return;
if (option_bool(OPT_NOWILD))
/* Can always get recvd interface for IPv6 */
if (!check_dest)
{
if (listen->iface)
{
+1 -1
View File
@@ -458,7 +458,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
int j, bytes = (1 + (r - in))/2;
for (j = 0; j < bytes; j++)
{
char sav;
char sav = sav;
if (j < bytes - 1)
{
sav = in[(j+1)*2];