mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Merge branch 'master' into dnssec
This commit is contained in:
31
CHANGELOG
31
CHANGELOG
@@ -1,3 +1,34 @@
|
||||
version 2.68
|
||||
Use random addresses for DHCPv6 temporary address
|
||||
allocations, instead of algorithmically determined stable
|
||||
addresses.
|
||||
|
||||
Fix bug which meant that the DHCPv6 DUID was not available
|
||||
in DHCP script runs during the lifetime of the dnsmasq
|
||||
process which created the DUID de-novo. Once the DUID was
|
||||
created and stored in the lease file and dnsmasq
|
||||
restarted, this bug disappeared.
|
||||
|
||||
Fix bug introduced in 2.67 which could result in erroneous
|
||||
NXDOMAIN returns to CNAME queries.
|
||||
|
||||
Fix build failures on MacOS X and openBSD.
|
||||
|
||||
Allow subnet specifications in --auth-zone to be interface
|
||||
names as well as address literals. This makes it possible
|
||||
to configure authoritative DNS when local address ranges
|
||||
are dynamic and works much better than the previous
|
||||
work-around which exempted contructed DHCP ranges from the
|
||||
IP address filtering. As a consequence, that work-around
|
||||
is removed. Under certain circumstances, this change wil
|
||||
break existing configuration: if you're relying on the
|
||||
contructed-range exception, you need to change --auth-zone
|
||||
to specify the same interface as is used to construct your
|
||||
DHCP ranges, probably with a trailing "/6" like this:
|
||||
--auth-zone=example.com,eth0/6 to limit the addresses to
|
||||
IPv6 addresses of eth0.
|
||||
|
||||
|
||||
version 2.67
|
||||
Fix crash if upstream server returns SERVFAIL when
|
||||
--conntrack in use. Thanks to Giacomo Tazzari for finding
|
||||
|
||||
@@ -589,10 +589,19 @@ needed for a client to do validation itself.
|
||||
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
|
||||
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
||||
will be served. A and AAAA records must be in one of the
|
||||
specified subnets, or in a subnet corresponding to a constructed DHCP
|
||||
range. (This can be overridden with
|
||||
.B constructor-noauth:
|
||||
) The subnet(s) are also used to define in-addr.arpa and
|
||||
specified subnets. As alternative to directly specifying the subnets, it's possible to
|
||||
give the name of an interface, in which case the subnets implied by
|
||||
that interface's configured addresses and netmask/prefix-length are
|
||||
used; this is useful when using constructed DHCP ranges as the actual
|
||||
address is dynamic and not known when configuring dnsmasq. The
|
||||
interface addresses may be confined to only IPv6 addresses using
|
||||
<interface>/6 or to only IPv4 using <interface>/4. This is useful when
|
||||
an interface has dynamically determined global IPv6 addresses which should
|
||||
appear in the zone, but RFC1918 IPv4 addresses which should not.
|
||||
Interface-name and address-literal subnet specifications may be used
|
||||
freely in the same --auth-zone declaration.
|
||||
|
||||
The subnet(s) are also used to define in-addr.arpa and
|
||||
ipv6.arpa domains which are served for reverse-DNS queries. If not
|
||||
specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
|
||||
For IPv4 subnets, the prefix length should be have the value 8, 16 or 24
|
||||
@@ -680,12 +689,6 @@ then the address can be simply ::
|
||||
.B --dhcp-range=::,constructor:eth0
|
||||
|
||||
|
||||
There is a variant of the constructor: syntax using the keyword
|
||||
.B constructor-noauth.
|
||||
See
|
||||
.B --auth-zone
|
||||
for an explanation of this.
|
||||
|
||||
The optional
|
||||
.B set:<tag>
|
||||
sets an alphanumeric label which marks this network so that
|
||||
@@ -1899,9 +1902,13 @@ Something like:
|
||||
.nf
|
||||
.B auth-server=our.zone.com,eth0
|
||||
.B interface-name=our.zone.com,eth0
|
||||
.B auth-zone=our.zone.com,1.2.3.0/24
|
||||
.B auth-zone=our.zone.com,1.2.3.0/24,eth0
|
||||
.fi
|
||||
|
||||
(The "eth0" argument in auth-zone adds the subnet containing eth0's
|
||||
dynamic address to the zone, so that the interface-name returns the
|
||||
address in outside queries.)
|
||||
|
||||
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
|
||||
@@ -1959,18 +1966,20 @@ IPv4 and IPv6 addresses from /etc/hosts (and
|
||||
.B --addn-hosts
|
||||
) and
|
||||
.B --host-record
|
||||
and
|
||||
.B --interface-name
|
||||
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.
|
||||
(If contructed DHCP ranges are is use, which depend on the address dynamically
|
||||
assigned to an interface, then the form of
|
||||
.B --auth-zone
|
||||
OR a constructed DHCP range. In the default mode, where a DHCP lease
|
||||
which defines subnets by the dynamic address of an interface should
|
||||
be used to ensure this condition is met.)
|
||||
.PP
|
||||
In the default mode, where a DHCP lease
|
||||
has an unqualified name, and possibly a qualified name constructed
|
||||
using
|
||||
.B --domain
|
||||
|
||||
81
src/auth.c
81
src/auth.c
@@ -18,27 +18,26 @@
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
|
||||
static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
static struct addrlist *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
struct subnet *subnet;
|
||||
struct addrlist *subnet;
|
||||
|
||||
for (subnet = zone->subnet; subnet; subnet = subnet->next)
|
||||
{
|
||||
if (subnet->is6 && (flag & F_IPV4))
|
||||
continue;
|
||||
|
||||
if (!subnet->is6)
|
||||
if (!(subnet->flags & ADDRLIST_IPV6))
|
||||
{
|
||||
struct in_addr addr = addr_u->addr.addr4;
|
||||
struct in_addr mask;
|
||||
struct in_addr netmask, addr = addr_u->addr.addr4;
|
||||
|
||||
if (!(flag & F_IPV4))
|
||||
continue;
|
||||
|
||||
mask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
|
||||
netmask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
|
||||
|
||||
if (is_same_net(addr, subnet->addr4, mask))
|
||||
if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
|
||||
return subnet;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr6, subnet->prefixlen))
|
||||
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
|
||||
return subnet;
|
||||
#endif
|
||||
|
||||
@@ -46,22 +45,6 @@ static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_a
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int filter_constructed_dhcp(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
struct dhcp_context *context;
|
||||
|
||||
if (flag & F_IPV6)
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if ((context->flags & CONTEXT_CONSTRUCTED) &&
|
||||
!(context->flags & CONTEXT_NOAUTH) &&
|
||||
is_same_net6(&(addr_u->addr.addr6), &context->start6, context->prefix))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return filter_zone(zone, flag, addr_u) != NULL;
|
||||
}
|
||||
|
||||
int in_zone(struct auth_zone *zone, char *name, char **cut)
|
||||
{
|
||||
size_t namelen = strlen(name);
|
||||
@@ -99,7 +82,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
struct crec *crecp;
|
||||
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
|
||||
struct auth_zone *zone = NULL;
|
||||
struct subnet *subnet = NULL;
|
||||
struct addrlist *subnet = NULL;
|
||||
char *cut;
|
||||
struct mx_srv_record *rec, *move, **up;
|
||||
struct txt_record *txt;
|
||||
@@ -164,8 +147,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
|
||||
if (addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
|
||||
break;
|
||||
|
||||
if (addrlist)
|
||||
@@ -180,8 +163,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
|
||||
if (IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
|
||||
break;
|
||||
|
||||
if (addrlist)
|
||||
@@ -362,16 +345,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
addrlist = intr->addr4;
|
||||
#ifdef HAVE_IPV6
|
||||
if (qtype == T_AAAA)
|
||||
addrlist = intr->addr6;
|
||||
#endif
|
||||
nxdomain = 0;
|
||||
|
||||
if (flag)
|
||||
for (; addrlist; addrlist = addrlist->next)
|
||||
if (local_query || filter_constructed_dhcp(zone, flag, &addrlist->addr))
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
|
||||
(local_query || filter_zone(zone, flag, &addrlist->addr)))
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||
@@ -468,7 +447,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
nxdomain = 0;
|
||||
if ((crecp->flags & flag) &&
|
||||
(local_query || filter_constructed_dhcp(zone, flag, &(crecp->addr.addr))))
|
||||
(local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
|
||||
{
|
||||
*cut = '.'; /* restore domain part */
|
||||
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||
@@ -491,7 +470,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
do
|
||||
{
|
||||
nxdomain = 0;
|
||||
if ((crecp->flags & flag) && (local_query || filter_constructed_dhcp(zone, flag, &(crecp->addr.addr))))
|
||||
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
|
||||
{
|
||||
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||
found = 1;
|
||||
@@ -522,9 +501,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
|
||||
authname = name;
|
||||
|
||||
if (!subnet->is6)
|
||||
if (!(subnet->flags & ADDRLIST_IPV6))
|
||||
{
|
||||
in_addr_t a = ntohl(subnet->addr4.s_addr) >> 8;
|
||||
in_addr_t a = ntohl(subnet->addr.addr.addr4.s_addr) >> 8;
|
||||
char *p = name;
|
||||
|
||||
if (subnet->prefixlen >= 24)
|
||||
@@ -544,7 +523,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
|
||||
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
|
||||
{
|
||||
int dig = ((unsigned char *)&subnet->addr6)[i>>3];
|
||||
int dig = ((unsigned char *)&subnet->addr.addr.addr6)[i>>3];
|
||||
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
||||
}
|
||||
p += sprintf(p, "ip6.arpa");
|
||||
@@ -680,15 +659,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
|
||||
if ((local_query || filter_constructed_dhcp(zone, F_IPV4, &addrlist->addr)) &&
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (!(subnet->flags & ADDRLIST_IPV6) &&
|
||||
(local_query || filter_zone(zone, F_IPV4, &addrlist->addr)) &&
|
||||
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
|
||||
anscount++;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
|
||||
if ((local_query || filter_constructed_dhcp(zone, F_IPV6, &addrlist->addr)) &&
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if ((subnet->flags & ADDRLIST_IPV6) &&
|
||||
(local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
|
||||
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
|
||||
anscount++;
|
||||
@@ -729,7 +710,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
char *cache_name = cache_get_name(crecp);
|
||||
if (!strchr(cache_name, '.') &&
|
||||
(local_query || filter_constructed_dhcp(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
||||
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
||||
{
|
||||
qtype = T_A;
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -747,7 +728,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
strcpy(name, cache_get_name(crecp));
|
||||
if (in_zone(zone, name, &cut) &&
|
||||
(local_query || filter_constructed_dhcp(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
||||
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
||||
{
|
||||
qtype = T_A;
|
||||
#ifdef HAVE_IPV6
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
# include <net/if_var.h>
|
||||
#endif
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet6/in6_var.h>
|
||||
|
||||
#ifndef SA_SIZE
|
||||
#define SA_SIZE(sa) \
|
||||
@@ -145,7 +146,7 @@ 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 defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||
struct in6_ifreq ifr6;
|
||||
|
||||
memset(&ifr6, 0, sizeof(ifr6));
|
||||
|
||||
@@ -330,7 +330,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
|
||||
((flags & crecp->flags & F_TYPE) || ((crecp->flags | flags) & F_CNAME)) &&
|
||||
hostname_isequal(cache_get_name(crecp), name))
|
||||
{
|
||||
if (crecp->flags & (F_HOSTS | F_DHCP))
|
||||
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
||||
return 0;
|
||||
*up = crecp->hash_next;
|
||||
cache_unlink(crecp);
|
||||
|
||||
@@ -255,7 +255,10 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
/* Define before sys/socket.h is included so we get socklen_t */
|
||||
#define _BSD_SOCKLEN_T_
|
||||
|
||||
/* Select the RFC_3542 version of the IPv6 socket API.
|
||||
Define before netinet6/in6.h is included. */
|
||||
#define __APPLE_USE_RFC_3542
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
|
||||
56
src/dhcp6.c
56
src/dhcp6.c
@@ -394,7 +394,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
|
||||
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
|
||||
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
|
||||
{
|
||||
/* Find a free address: exclude anything in use and anything allocated to
|
||||
@@ -411,9 +411,13 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
|
||||
u64 j;
|
||||
|
||||
/* hash hwaddr: use the SDBM hashing algorithm. This works
|
||||
for MAC addresses, let's see how it manages with client-ids! */
|
||||
for (j = iaid, i = 0; i < clid_len; i++)
|
||||
j += clid[i] + (j << 6) + (j << 16) - j;
|
||||
for MAC addresses, let's see how it manages with client-ids!
|
||||
For temporary addresses, we generate a new random one each time. */
|
||||
if (temp_addr)
|
||||
j = rand64();
|
||||
else
|
||||
for (j = iaid, i = 0; i < clid_len; i++)
|
||||
j += clid[i] + (j << 6) + (j << 16) - j;
|
||||
|
||||
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
|
||||
for (c = context; c; c = c->current)
|
||||
@@ -423,7 +427,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
|
||||
continue;
|
||||
else
|
||||
{
|
||||
if (option_bool(OPT_CONSEC_ADDR))
|
||||
if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
|
||||
/* seed is largest extant lease addr in this context */
|
||||
start = lease_find_max_addr6(c) + serial;
|
||||
else
|
||||
@@ -523,6 +527,8 @@ int config_valid(struct dhcp_config *config, struct dhcp_context *context, struc
|
||||
|
||||
void make_duid(time_t now)
|
||||
{
|
||||
(void)now;
|
||||
|
||||
if (daemon->duid_config)
|
||||
{
|
||||
unsigned char *p;
|
||||
@@ -535,8 +541,14 @@ void make_duid(time_t now)
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t newnow = 0;
|
||||
|
||||
/* If we have no persistent lease database, or a non-stable RTC, use DUID_LL (newnow == 0) */
|
||||
#ifndef HAVE_BROKEN_RTC
|
||||
/* rebase epoch to 1/1/2000 */
|
||||
time_t newnow = now - 946684800;
|
||||
if (!option_bool(OPT_LEASE_RO) || daemon->lease_change_command)
|
||||
newnow = now - 946684800;
|
||||
#endif
|
||||
|
||||
iface_enumerate(AF_LOCAL, &newnow, make_duid1);
|
||||
|
||||
@@ -555,23 +567,27 @@ static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, vo
|
||||
unsigned char *p;
|
||||
(void)index;
|
||||
(void)parm;
|
||||
|
||||
time_t newnow = *((time_t *)parm);
|
||||
|
||||
if (type >= 256)
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
daemon->duid = p = safe_malloc(maclen + 4);
|
||||
daemon->duid_len = maclen + 4;
|
||||
PUTSHORT(3, p); /* DUID_LL */
|
||||
PUTSHORT(type, p); /* address type */
|
||||
#else
|
||||
daemon->duid = p = safe_malloc(maclen + 8);
|
||||
daemon->duid_len = maclen + 8;
|
||||
PUTSHORT(1, p); /* DUID_LLT */
|
||||
PUTSHORT(type, p); /* address type */
|
||||
PUTLONG(*((time_t *)parm), p); /* time */
|
||||
#endif
|
||||
|
||||
if (newnow == 0)
|
||||
{
|
||||
daemon->duid = p = safe_malloc(maclen + 4);
|
||||
daemon->duid_len = maclen + 4;
|
||||
PUTSHORT(3, p); /* DUID_LL */
|
||||
PUTSHORT(type, p); /* address type */
|
||||
}
|
||||
else
|
||||
{
|
||||
daemon->duid = p = safe_malloc(maclen + 8);
|
||||
daemon->duid_len = maclen + 8;
|
||||
PUTSHORT(1, p); /* DUID_LLT */
|
||||
PUTSHORT(type, p); /* address type */
|
||||
PUTLONG(*((time_t *)parm), p); /* time */
|
||||
}
|
||||
|
||||
memcpy(p, mac, maclen);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -274,6 +274,9 @@ int main (int argc, char **argv)
|
||||
/* after enumerate_interfaces() */
|
||||
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
|
||||
join_multicast(1);
|
||||
|
||||
/* After netlink_init() and before create_helper() */
|
||||
lease_make_duid(now);
|
||||
#endif
|
||||
|
||||
if (daemon->port != 0)
|
||||
|
||||
@@ -284,18 +284,28 @@ struct ptr_record {
|
||||
struct cname {
|
||||
char *alias, *target;
|
||||
struct cname *next;
|
||||
};
|
||||
|
||||
#define ADDRLIST_LITERAL 1
|
||||
#define ADDRLIST_IPV6 2
|
||||
|
||||
struct addrlist {
|
||||
struct all_addr addr;
|
||||
int flags, prefixlen;
|
||||
struct addrlist *next;
|
||||
};
|
||||
|
||||
#define AUTH6 1
|
||||
#define AUTH4 2
|
||||
|
||||
struct auth_zone {
|
||||
char *domain;
|
||||
struct subnet {
|
||||
int is6, prefixlen;
|
||||
struct in_addr addr4;
|
||||
#ifdef HAVE_IPV6
|
||||
struct in6_addr addr6;
|
||||
#endif
|
||||
struct subnet *next;
|
||||
} *subnet;
|
||||
struct auth_name_list {
|
||||
char *name;
|
||||
int flags;
|
||||
struct auth_name_list *next;
|
||||
} *interface_names;
|
||||
struct addrlist *subnet;
|
||||
struct auth_zone *next;
|
||||
};
|
||||
|
||||
@@ -315,13 +325,7 @@ struct host_record {
|
||||
struct interface_name {
|
||||
char *name; /* domain name */
|
||||
char *intr; /* interface name */
|
||||
struct addrlist {
|
||||
struct all_addr addr;
|
||||
struct addrlist *next;
|
||||
} *addr4;
|
||||
#ifdef HAVE_IPV6
|
||||
struct addrlist *addr6;
|
||||
#endif
|
||||
struct addrlist *addr;
|
||||
struct interface_name *next;
|
||||
};
|
||||
|
||||
@@ -752,9 +756,8 @@ struct dhcp_context {
|
||||
#define CONTEXT_RA (1u<<13)
|
||||
#define CONTEXT_CONF_USED (1u<<14)
|
||||
#define CONTEXT_USED (1u<<15)
|
||||
#define CONTEXT_NOAUTH (1u<<16)
|
||||
#define CONTEXT_OLD (1u<<17)
|
||||
#define CONTEXT_V6 (1u<<18)
|
||||
#define CONTEXT_OLD (1u<<16)
|
||||
#define CONTEXT_V6 (1u<<17)
|
||||
|
||||
|
||||
struct ping_result {
|
||||
@@ -1012,6 +1015,7 @@ int dnssec_validate(struct dns_header *header, size_t plen);
|
||||
/* util.c */
|
||||
void rand_init(void);
|
||||
unsigned short rand16(void);
|
||||
u64 rand64(void);
|
||||
int legal_hostname(char *c);
|
||||
char *canonicalise(char *s, int *nomem);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
|
||||
@@ -1132,6 +1136,7 @@ u64 lease_find_max_addr6(struct dhcp_context *context);
|
||||
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
|
||||
void lease_update_slaac(time_t now);
|
||||
void lease_set_iaid(struct dhcp_lease *lease, int iaid);
|
||||
void lease_make_duid(time_t now);
|
||||
#endif
|
||||
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
|
||||
@@ -1232,7 +1237,7 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
|
||||
#ifdef HAVE_DHCP6
|
||||
void dhcp6_init(void);
|
||||
void dhcp6_packet(time_t now);
|
||||
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len,
|
||||
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
|
||||
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
|
||||
int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
|
||||
struct dhcp_context *address6_available(struct dhcp_context *context,
|
||||
|
||||
10
src/lease.c
10
src/lease.c
@@ -417,15 +417,21 @@ void lease_find_interfaces(time_t now)
|
||||
iface_enumerate(AF_INET, &now, find_interface_v4);
|
||||
#ifdef HAVE_DHCP6
|
||||
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
void lease_make_duid(time_t now)
|
||||
{
|
||||
/* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
|
||||
if (!daemon->duid && daemon->dhcp6)
|
||||
if (!daemon->duid && daemon->doing_dhcp6)
|
||||
{
|
||||
file_dirty = 1;
|
||||
make_duid(now);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
120
src/network.c
120
src/network.c
@@ -239,7 +239,7 @@ struct iface_param {
|
||||
};
|
||||
|
||||
static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
union mysockaddr *addr, struct in_addr netmask, int dad)
|
||||
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad)
|
||||
{
|
||||
struct irec *iface;
|
||||
int mtu = 0, loopback;
|
||||
@@ -267,15 +267,67 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
label = ifr.ifr_name;
|
||||
|
||||
|
||||
/* Update addresses from interface_names. These are a set independent
|
||||
of the set we're listening on. */
|
||||
#ifdef HAVE_IPV6
|
||||
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
|
||||
#endif
|
||||
{
|
||||
struct interface_name *int_name;
|
||||
struct addrlist *al;
|
||||
#ifdef HAVE_AUTH
|
||||
struct auth_zone *zone;
|
||||
struct auth_name_list *name;
|
||||
|
||||
/* Find subnets in auth_zones */
|
||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||
for (name = zone->interface_names; name; name = name->next)
|
||||
if (wildcard_match(name->name, label))
|
||||
{
|
||||
if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
|
||||
{
|
||||
if (param->spare)
|
||||
{
|
||||
al = param->spare;
|
||||
param->spare = al->next;
|
||||
}
|
||||
else
|
||||
al = whine_malloc(sizeof(struct addrlist));
|
||||
|
||||
if (al)
|
||||
{
|
||||
al->next = zone->subnet;
|
||||
zone->subnet = al;
|
||||
al->prefixlen = prefixlen;
|
||||
al->addr.addr.addr4 = addr->in.sin_addr;
|
||||
al->flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
|
||||
{
|
||||
if (param->spare)
|
||||
{
|
||||
al = param->spare;
|
||||
param->spare = al->next;
|
||||
}
|
||||
else
|
||||
al = whine_malloc(sizeof(struct addrlist));
|
||||
|
||||
if (al)
|
||||
{
|
||||
al->next = zone->subnet;
|
||||
zone->subnet = al;
|
||||
al->prefixlen = prefixlen;al->addr.addr.addr6 = addr->in6.sin6_addr;
|
||||
al->flags = ADDRLIST_IPV6;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update addresses from interface_names. These are a set independent
|
||||
of the set we're listening on. */
|
||||
for (int_name = daemon->int_names; int_name; int_name = int_name->next)
|
||||
if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
|
||||
{
|
||||
@@ -289,18 +341,19 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
|
||||
if (al)
|
||||
{
|
||||
al->next = int_name->addr;
|
||||
int_name->addr = al;
|
||||
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
{
|
||||
al->addr.addr.addr4 = addr->in.sin_addr;
|
||||
al->next = int_name->addr4;
|
||||
int_name->addr4 = al;
|
||||
al->flags = 0;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
al->addr.addr.addr6 = addr->in6.sin6_addr;
|
||||
al->next = int_name->addr6;
|
||||
int_name->addr6 = al;
|
||||
al->flags = ADDRLIST_IPV6;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -413,7 +466,6 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
||||
struct in_addr netmask; /* dummy */
|
||||
netmask.s_addr = 0;
|
||||
|
||||
(void)prefix; /* warning */
|
||||
(void)scope; /* warning */
|
||||
(void)preferred;
|
||||
(void)valid;
|
||||
@@ -427,7 +479,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
||||
addr.in6.sin6_port = htons(daemon->port);
|
||||
addr.in6.sin6_scope_id = if_index;
|
||||
|
||||
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
||||
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -435,6 +487,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
int prefix, bit;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
@@ -445,7 +498,10 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
||||
addr.in.sin_addr = local;
|
||||
addr.in.sin_port = htons(daemon->port);
|
||||
|
||||
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, 0);
|
||||
/* determine prefix length from netmask */
|
||||
for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
|
||||
|
||||
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
|
||||
}
|
||||
|
||||
int enumerate_interfaces(int reset)
|
||||
@@ -456,7 +512,10 @@ int enumerate_interfaces(int reset)
|
||||
int errsave, ret = 1;
|
||||
struct addrlist *addr, *tmp;
|
||||
struct interface_name *intname;
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
struct auth_zone *zone;
|
||||
#endif
|
||||
|
||||
/* Do this max once per select cycle - also inhibits netlink socket use
|
||||
in TCP child processes. */
|
||||
|
||||
@@ -480,27 +539,38 @@ int enumerate_interfaces(int reset)
|
||||
/* remove addresses stored against interface_names */
|
||||
for (intname = daemon->int_names; intname; intname = intname->next)
|
||||
{
|
||||
for (addr = intname->addr4; addr; addr = tmp)
|
||||
for (addr = intname->addr; addr; addr = tmp)
|
||||
{
|
||||
tmp = addr->next;
|
||||
addr->next = spare;
|
||||
spare = addr;
|
||||
}
|
||||
|
||||
intname->addr4 = NULL;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
for (addr = intname->addr6; addr; addr = tmp)
|
||||
{
|
||||
tmp = addr->next;
|
||||
addr->next = spare;
|
||||
spare = addr;
|
||||
}
|
||||
|
||||
intname->addr6 = NULL;
|
||||
#endif
|
||||
intname->addr = NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
/* remove addresses stored against auth_zone subnets, but not
|
||||
ones configured as address literals */
|
||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||
if (zone->interface_names)
|
||||
{
|
||||
struct addrlist **up;
|
||||
for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
|
||||
{
|
||||
tmp = addr->next;
|
||||
if (addr->flags & ADDRLIST_LITERAL)
|
||||
up = &addr->next;
|
||||
else
|
||||
{
|
||||
*up = addr->next;
|
||||
addr->next = spare;
|
||||
spare = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
param.spare = spare;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
|
||||
58
src/option.c
58
src/option.c
@@ -1654,6 +1654,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
new = opt_malloc(sizeof(struct auth_zone));
|
||||
new->domain = opt_string_alloc(arg);
|
||||
new->subnet = NULL;
|
||||
new->interface_names = NULL;
|
||||
new->next = daemon->auth_zones;
|
||||
daemon->auth_zones = new;
|
||||
|
||||
@@ -1661,10 +1662,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
{
|
||||
int prefixlen = 0;
|
||||
char *prefix;
|
||||
struct subnet *subnet = opt_malloc(sizeof(struct subnet));
|
||||
|
||||
subnet->next = new->subnet;
|
||||
new->subnet = subnet;
|
||||
struct addrlist *subnet = NULL;
|
||||
struct all_addr addr;
|
||||
|
||||
comma = split(arg);
|
||||
prefix = split_chr(arg, '/');
|
||||
@@ -1672,24 +1671,50 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
if (prefix && !atoi_check(prefix, &prefixlen))
|
||||
ret_err(gen_err);
|
||||
|
||||
if (inet_pton(AF_INET, arg, &subnet->addr4))
|
||||
if (inet_pton(AF_INET, arg, &addr.addr.addr4))
|
||||
{
|
||||
subnet = opt_malloc(sizeof(struct addrlist));
|
||||
subnet->prefixlen = (prefixlen == 0) ? 24 : prefixlen;
|
||||
subnet->is6 = 0;
|
||||
subnet->flags = ADDRLIST_LITERAL;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, arg, &subnet->addr6))
|
||||
else if (inet_pton(AF_INET6, arg, &addr.addr.addr6))
|
||||
{
|
||||
subnet = opt_malloc(sizeof(struct addrlist));
|
||||
subnet->prefixlen = (prefixlen == 0) ? 64 : prefixlen;
|
||||
subnet->is6 = 1;
|
||||
subnet->flags = ADDRLIST_LITERAL | ADDRLIST_IPV6;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ret_err(gen_err);
|
||||
else
|
||||
{
|
||||
struct auth_name_list *name = opt_malloc(sizeof(struct auth_name_list));
|
||||
name->name = opt_string_alloc(arg);
|
||||
name->flags = AUTH4 | AUTH6;
|
||||
name->next = new->interface_names;
|
||||
new->interface_names = name;
|
||||
if (prefix)
|
||||
{
|
||||
if (prefixlen == 4)
|
||||
name->flags &= ~AUTH6;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (prefixlen == 6)
|
||||
name->flags &= ~AUTH4;
|
||||
#endif
|
||||
else
|
||||
ret_err(gen_err);
|
||||
}
|
||||
}
|
||||
|
||||
if (subnet)
|
||||
{
|
||||
subnet->addr = addr;
|
||||
subnet->next = new->subnet;
|
||||
new->subnet = subnet;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case LOPT_AUTHSOA: /* --auth-soa */
|
||||
comma = split(arg);
|
||||
daemon->soa_sn = (u32)atoi(arg);
|
||||
@@ -2469,11 +2494,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
new->template_interface = opt_string_alloc(a[leasepos] + 12);
|
||||
new->flags |= CONTEXT_TEMPLATE;
|
||||
}
|
||||
else if (strstr(a[leasepos], "constructor-noauth:") == a[leasepos])
|
||||
{
|
||||
new->template_interface = opt_string_alloc(a[leasepos] + 19);
|
||||
new->flags |= CONTEXT_TEMPLATE | CONTEXT_NOAUTH;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
@@ -3340,10 +3360,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
|
||||
new = opt_malloc(sizeof(struct interface_name));
|
||||
new->next = NULL;
|
||||
new->addr4 = NULL;
|
||||
#ifdef HAVE_IPV6
|
||||
new->addr6 = NULL;
|
||||
#endif
|
||||
new->addr = NULL;
|
||||
|
||||
/* Add to the end of the list, so that first name
|
||||
of an interface is used for PTR lookups. */
|
||||
for (up = &daemon->int_names; *up; up = &((*up)->next));
|
||||
|
||||
@@ -637,7 +637,7 @@ struct subnet_opt {
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
|
||||
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
|
||||
{
|
||||
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
|
||||
|
||||
@@ -1221,7 +1221,7 @@ int check_for_local_domain(char *name, time_t now)
|
||||
struct naptr *naptr;
|
||||
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME)) &&
|
||||
(crecp->flags & (F_HOSTS | F_DHCP)))
|
||||
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
|
||||
return 1;
|
||||
|
||||
for (naptr = daemon->naptr; naptr; naptr = naptr->next)
|
||||
@@ -1550,8 +1550,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
for (addrlist = intr->addr4; addrlist; addrlist = addrlist->next)
|
||||
if (addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
|
||||
break;
|
||||
|
||||
if (addrlist)
|
||||
@@ -1566,8 +1566,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
for (addrlist = intr->addr6; addrlist; addrlist = addrlist->next)
|
||||
if (IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
|
||||
break;
|
||||
|
||||
if (addrlist)
|
||||
@@ -1732,26 +1732,22 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (hostname_isequal(name, intr->name))
|
||||
{
|
||||
addrlist = intr->addr4;
|
||||
#ifdef HAVE_IPV6
|
||||
if (type == T_AAAA)
|
||||
addrlist = intr->addr6;
|
||||
#endif
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
{
|
||||
if (addrlist)
|
||||
{
|
||||
gotit = 1;
|
||||
for (; addrlist; addrlist = addrlist->next)
|
||||
{
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &addrlist->addr))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
#ifdef HAVE_IPV6
|
||||
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
|
||||
#endif
|
||||
{
|
||||
gotit = 1;
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL, type, C_IN,
|
||||
type == T_A ? "4" : "6", &addrlist->addr))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1861,7 +1857,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
if (qtype == T_CNAME || qtype == T_ANY)
|
||||
{
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
|
||||
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP))))
|
||||
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))))
|
||||
{
|
||||
ans = 1;
|
||||
if (!dryrun)
|
||||
|
||||
@@ -764,7 +764,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
|
||||
/* Return addresses for all valid contexts which don't yet have one */
|
||||
while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
|
||||
while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->ia_type == OPTION6_IA_TA,
|
||||
state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
|
||||
{
|
||||
#ifdef OPTION6_PREFIX_CLASS
|
||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
||||
|
||||
37
src/util.c
37
src/util.c
@@ -39,6 +39,15 @@ unsigned short rand16(void)
|
||||
return (unsigned short) (arc4random() >> 15);
|
||||
}
|
||||
|
||||
u64 rand64(void)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
arc4random_buf(&ret, sizeof(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* SURF random number generator */
|
||||
@@ -46,6 +55,7 @@ unsigned short rand16(void)
|
||||
static u32 seed[32];
|
||||
static u32 in[12];
|
||||
static u32 out[8];
|
||||
static int outleft = 0;
|
||||
|
||||
void rand_init()
|
||||
{
|
||||
@@ -82,16 +92,31 @@ static void surf(void)
|
||||
}
|
||||
|
||||
unsigned short rand16(void)
|
||||
{
|
||||
if (!outleft)
|
||||
{
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
|
||||
return (unsigned short) out[--outleft];
|
||||
}
|
||||
|
||||
u64 rand64(void)
|
||||
{
|
||||
static int outleft = 0;
|
||||
|
||||
if (!outleft) {
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
if (outleft < 2)
|
||||
{
|
||||
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||
surf();
|
||||
outleft = 8;
|
||||
}
|
||||
|
||||
outleft -= 2;
|
||||
|
||||
return (unsigned short) out[--outleft];
|
||||
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user