Merge branch 'master' into dnssec

This commit is contained in:
Simon Kelley
2013-11-14 10:39:40 +00:00
15 changed files with 353 additions and 188 deletions

View File

@@ -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

View File

@@ -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));

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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));

View File

@@ -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)

View File

@@ -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)

View File

@@ -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