|
|
e9e7d6 |
From 3d27384fc5f2a437b7bce128c8ba62e8d6e12df7 Mon Sep 17 00:00:00 2001
|
|
|
e9e7d6 |
From: Brian Haley <haleyb.dev@gmail.com>
|
|
|
e9e7d6 |
Date: Wed, 28 Aug 2019 16:13:23 -0400
|
|
|
e9e7d6 |
Subject: [PATCH] Change dhcp_release to use default address when no IP subnet
|
|
|
e9e7d6 |
matches
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
Currently, dhcp_release will only send a 'fake' release
|
|
|
e9e7d6 |
when the address given is in the same subnet as an IP
|
|
|
e9e7d6 |
on the interface that was given.
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
This doesn't work in an environment where dnsmasq is
|
|
|
e9e7d6 |
managing leases for remote subnets via a DHCP relay, as
|
|
|
e9e7d6 |
running dhcp_release locally will just cause it to
|
|
|
e9e7d6 |
silently exit without doing anything, leaving the lease
|
|
|
e9e7d6 |
in the database.
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
Change it to use the default IP on the interface, as the
|
|
|
e9e7d6 |
dnsmasq source code at src/dhcp.c does, if no matching subnet
|
|
|
e9e7d6 |
IP is found, as a fall-back. This fixes an issue we are
|
|
|
e9e7d6 |
seeing in certain Openstack deployments where we are using
|
|
|
e9e7d6 |
dnsmasq to provision baremetal systems in a datacenter.
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
While using Dbus might have seemed like an obvious solution,
|
|
|
e9e7d6 |
because of our extensive use of network namespaces (which
|
|
|
e9e7d6 |
Dbus doesn't support), this seemed like a better solution
|
|
|
e9e7d6 |
than creating system.d policy files for each dnsmasq we
|
|
|
e9e7d6 |
might spawn and using --enable-dbus=$id in order to isolate
|
|
|
e9e7d6 |
messages to specific dnsmasq instances.
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
Signed-off-by: Brian Haley <haleyb.dev@gmail.com>
|
|
|
e9e7d6 |
(cherry picked from commit d9f882bea2806799bf3d1f73937f5e72d0bfc650)
|
|
|
e9e7d6 |
---
|
|
|
e9e7d6 |
contrib/lease-tools/dhcp_release.c | 12 +++++++++---
|
|
|
e9e7d6 |
1 file changed, 9 insertions(+), 3 deletions(-)
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
diff --git a/contrib/lease-tools/dhcp_release.c b/contrib/lease-tools/dhcp_release.c
|
|
|
e9e7d6 |
index a51f04b..1dd8d32 100644
|
|
|
e9e7d6 |
--- a/contrib/lease-tools/dhcp_release.c
|
|
|
e9e7d6 |
+++ b/contrib/lease-tools/dhcp_release.c
|
|
|
e9e7d6 |
@@ -178,7 +178,7 @@ static int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
|
|
e9e7d6 |
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
|
|
e9e7d6 |
}
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
-static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index)
|
|
|
e9e7d6 |
+static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index, int ifrfd, struct ifreq *ifr)
|
|
|
e9e7d6 |
{
|
|
|
e9e7d6 |
struct sockaddr_nl addr;
|
|
|
e9e7d6 |
struct nlmsghdr *h;
|
|
|
e9e7d6 |
@@ -218,7 +218,13 @@ static struct in_addr find_interface(struct in_addr client, int fd, unsigned int
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
|
|
e9e7d6 |
if (h->nlmsg_type == NLMSG_DONE)
|
|
|
e9e7d6 |
- exit(0);
|
|
|
e9e7d6 |
+ {
|
|
|
e9e7d6 |
+ /* No match found, return first address as src/dhcp.c code does */
|
|
|
e9e7d6 |
+ ifr->ifr_addr.sa_family = AF_INET;
|
|
|
e9e7d6 |
+ if (ioctl(ifrfd, SIOCGIFADDR, ifr) != -1)
|
|
|
e9e7d6 |
+ return ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
|
|
|
e9e7d6 |
+ exit(0);
|
|
|
e9e7d6 |
+ }
|
|
|
e9e7d6 |
else if (h->nlmsg_type == RTM_NEWADDR)
|
|
|
e9e7d6 |
{
|
|
|
e9e7d6 |
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
|
|
e9e7d6 |
@@ -284,7 +290,7 @@ int main(int argc, char **argv)
|
|
|
e9e7d6 |
}
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
lease.s_addr = inet_addr(argv[2]);
|
|
|
e9e7d6 |
- server = find_interface(lease, nl, if_nametoindex(argv[1]));
|
|
|
e9e7d6 |
+ server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr);
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
memset(&packet, 0, sizeof(packet));
|
|
|
e9e7d6 |
|
|
|
e9e7d6 |
--
|
|
|
e9e7d6 |
2.20.1
|
|
|
e9e7d6 |
|