summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2012-09-08 21:47:28 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2012-09-08 21:47:28 +0100
commit8b46061e735f88fee6ecc7ceab4f3974e6bd38cb (patch)
treedd20fc20ddc5a6425be23497eb0237f86c87ade9 /src
parent4d0f5b4c44e66eb6c426180186b4619bd2f43046 (diff)
downloaddnsmasq-8b46061e735f88fee6ecc7ceab4f3974e6bd38cb.tar.gz
Fix DHCPv6 address allocation for some pathalogical cases.v2.64test4
Diffstat (limited to 'src')
-rw-r--r--src/dnsmasq.h1
-rw-r--r--src/lease.c27
-rw-r--r--src/rfc3315.c15
3 files changed, 31 insertions, 12 deletions
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index b131c96..5cbe0e5 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -992,6 +992,7 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr);
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
int lease_type, int iaid, struct in6_addr *addr);
+void lease6_filter(int lease_type, int iaid, struct dhcp_context *context);
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
u64 lease_find_max_addr6(struct dhcp_context *context);
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
diff --git a/src/lease.c b/src/lease.c
index cff24a2..5f91bc8 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -562,18 +562,31 @@ struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
memcmp(clid, lease->clid, clid_len) != 0))
continue;
- if (clid || addr)
- {
- lease->flags |= LEASE_USED;
- return lease;
- }
- else
- lease->flags &= ~LEASE_USED;
+ lease->flags |= LEASE_USED;
+ return lease;
}
return NULL;
}
+void lease6_filter(int lease_type, int iaid, struct dhcp_context *context)
+{
+ struct dhcp_lease *lease;
+
+ for (lease = leases; lease; lease = lease->next)
+ {
+ /* reset "USED flag */
+ lease->flags &= ~LEASE_USED;
+
+ if (!(lease->flags & lease_type) || lease->hwaddr_type != iaid)
+ continue;
+
+ /* leases on the wrong interface get filtered out here */
+ if (!address6_available(context, (struct in6_addr *)&lease->hwaddr, NULL))
+ lease->flags |= LEASE_USED;
+ }
+}
+
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr)
{
struct dhcp_lease *lease;
diff --git a/src/rfc3315.c b/src/rfc3315.c
index a1c8326..14cbc66 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -497,7 +497,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
ia_option = opt6_find(opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4), ia_end, OPTION6_IAADDR, 24);
/* reset "USED" flags on leases */
- lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+ lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
o = new_opt6(ia_type);
put_opt6_long(iaid);
@@ -570,7 +570,12 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"),
daemon->addrbuff);
else
- addrp = &config->addr6;
+ {
+ addrp = &config->addr6;
+ /* may have existing lease for this address */
+ lease = lease6_find(clid, clid_len,
+ ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, addrp);
+ }
}
/* existing lease */
@@ -832,7 +837,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
iacntr = save_counter(-1);
/* reset "USED" flags on leases */
- lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+ lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
ia_end = opt6_ptr(opt, opt6_len(opt));
@@ -1036,7 +1041,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
/* reset "USED" flags on leases */
- lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+ lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
ia_option;
@@ -1115,7 +1120,7 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
ia_option = opt6_ptr(opt, ia_type == OPTION6_IA_NA ? 12 : 4);
/* reset "USED" flags on leases */
- lease6_find(NULL, 0, ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, NULL);
+ lease6_filter(ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, iaid, context);
for (ia_option = opt6_find(ia_option, ia_end, OPTION6_IAADDR, 24);
ia_option;