Set interface with longest prefix in DHCP & DHCPv6 lease

- With nested prefixes reside on different interfaces of single host

  (e.g., in 6to4, 2002::/16 on WAN and 2002:<IPv4>:<subnet>::/64 on LAN),

  current matching mechanism might return the interface with shorter prefix

  length instead of the longer one, if it appears later in the netlink message.

Signed-off-by: Lung-Pin Chang <changlp@cs.nctu.edu.tw>
This commit is contained in:
Lung-Pin Chang
2014-07-02 10:48:05 +08:00
parent cdb755c5f1
commit dc8a1b1bcf
3 changed files with 47 additions and 9 deletions

View File

@@ -352,16 +352,21 @@ static int find_interface_v4(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, void *vparam)
{
struct dhcp_lease *lease;
int prefix;
(void) label;
(void) broadcast;
(void) vparam;
for (lease = leases; lease; lease = lease->next)
if (!(lease->flags & (LEASE_TA | LEASE_NA)))
if (is_same_net(local, lease->addr, netmask))
lease_set_interface(lease, if_index, *((time_t *)vparam));
if (!(lease->flags & (LEASE_TA | LEASE_NA))) {
prefix = netmask_length(netmask);
if (is_same_net(local, lease->addr, netmask) && prefix > lease->new_prefixlen) {
lease->new_interface = if_index;
lease->new_prefixlen = prefix;
}
}
return 1;
}
@@ -371,17 +376,23 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
int preferred, int valid, void *vparam)
{
struct dhcp_lease *lease;
(void)scope;
(void)flags;
(void)preferred;
(void)valid;
(void)vparam;
for (lease = leases; lease; lease = lease->next)
if ((lease->flags & (LEASE_TA | LEASE_NA)))
if (is_same_net6(local, &lease->addr6, prefix))
lease_set_interface(lease, if_index, *((time_t *)vparam));
if (is_same_net6(local, &lease->addr6, prefix) && prefix > lease->new_prefixlen) {
/* save prefix length for comparison, as we might get shorter matching
* prefix in upcoming netlink GETADDR responses
* */
lease->new_interface = if_index;
lease->new_prefixlen = prefix;
}
return 1;
}
@@ -418,6 +429,7 @@ void lease_find_interfaces(time_t now)
#ifdef HAVE_DHCP6
iface_enumerate(AF_INET6, &now, find_interface_v6);
#endif
lease_update_interface(now);
}
#ifdef HAVE_DHCP6
@@ -492,6 +504,16 @@ void lease_update_dns(int force)
}
}
void lease_update_interface(time_t now)
{
struct dhcp_lease *lease;
for (lease = leases; lease; lease = lease->next)
if (lease->new_interface > 0) {
lease_set_interface(lease, lease->new_interface, now);
}
}
void lease_prune(struct dhcp_lease *target, time_t now)
{
struct dhcp_lease *lease, *tmp, **up;