diff options
author | Simon Kelley <simon@thekelleys.org.uk> | 2012-09-08 21:47:28 +0100 |
---|---|---|
committer | Simon Kelley <simon@thekelleys.org.uk> | 2012-09-08 21:47:28 +0100 |
commit | 8b46061e735f88fee6ecc7ceab4f3974e6bd38cb (patch) | |
tree | dd20fc20ddc5a6425be23497eb0237f86c87ade9 | |
parent | 4d0f5b4c44e66eb6c426180186b4619bd2f43046 (diff) | |
download | dnsmasq-8b46061e735f88fee6ecc7ceab4f3974e6bd38cb.tar.gz |
Fix DHCPv6 address allocation for some pathalogical cases.v2.64test4
-rw-r--r-- | src/dnsmasq.h | 1 | ||||
-rw-r--r-- | src/lease.c | 27 | ||||
-rw-r--r-- | src/rfc3315.c | 15 |
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; |