mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
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:
@@ -640,6 +640,8 @@ struct dhcp_lease {
|
||||
unsigned char *extradata;
|
||||
unsigned int extradata_len, extradata_size;
|
||||
int last_interface;
|
||||
int new_interface; /* save possible originated interface */
|
||||
int new_prefixlen; /* and its prefix length */
|
||||
#ifdef HAVE_DHCP6
|
||||
struct in6_addr addr6;
|
||||
int iaid;
|
||||
@@ -1131,6 +1133,7 @@ int sa_len(union mysockaddr *addr);
|
||||
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
||||
int hostname_isequal(const char *a, const char *b);
|
||||
time_t dnsmasq_time(void);
|
||||
int netmask_length(struct in_addr mask);
|
||||
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||
#ifdef HAVE_IPV6
|
||||
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
|
||||
@@ -1242,6 +1245,7 @@ char *host_from_dns(struct in_addr addr);
|
||||
#ifdef HAVE_DHCP
|
||||
void lease_update_file(time_t now);
|
||||
void lease_update_dns(int force);
|
||||
void lease_update_interface(time_t now);
|
||||
void lease_init(time_t now);
|
||||
struct dhcp_lease *lease4_allocate(struct in_addr addr);
|
||||
#ifdef HAVE_DHCP6
|
||||
|
||||
32
src/lease.c
32
src/lease.c
@@ -352,15 +352,20 @@ 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;
|
||||
}
|
||||
@@ -376,11 +381,17 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
|
||||
(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;
|
||||
|
||||
12
src/util.c
12
src/util.c
@@ -319,6 +319,18 @@ time_t dnsmasq_time(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int netmask_length(struct in_addr mask)
|
||||
{
|
||||
int zero_count = 0;
|
||||
|
||||
while (0x0 == (mask.s_addr & 0x1)) {
|
||||
mask.s_addr >>= 1;
|
||||
++zero_count;
|
||||
}
|
||||
|
||||
return 32 - zero_count;
|
||||
}
|
||||
|
||||
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
||||
{
|
||||
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
||||
|
||||
Reference in New Issue
Block a user