|
|
eabdae |
From 11ab42e63f9089c4c14a391f30175d4c2d071e99 Mon Sep 17 00:00:00 2001
|
|
|
eabdae |
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
|
|
eabdae |
Date: Mon, 15 Jul 2019 17:13:12 +0200
|
|
|
eabdae |
Subject: [PATCH 4/5] Handle listening on duplicate addresses
|
|
|
eabdae |
|
|
|
eabdae |
Save listening address into listener. Use it to find existing listeners
|
|
|
eabdae |
before creating new one. If it exist, increase just used counter.
|
|
|
eabdae |
Release only listeners not already used.
|
|
|
eabdae |
|
|
|
eabdae |
Duplicates family in listener.
|
|
|
eabdae |
---
|
|
|
eabdae |
src/dnsmasq.h | 3 +-
|
|
|
eabdae |
src/network.c | 115 ++++++++++++++++++++++++++++++++++++--------------
|
|
|
eabdae |
2 files changed, 85 insertions(+), 33 deletions(-)
|
|
|
eabdae |
|
|
|
eabdae |
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
|
|
eabdae |
index 89d138a..3b3f6ef 100644
|
|
|
eabdae |
--- a/src/dnsmasq.h
|
|
|
eabdae |
+++ b/src/dnsmasq.h
|
|
|
eabdae |
@@ -552,7 +552,8 @@ struct irec {
|
|
|
eabdae |
};
|
|
|
eabdae |
|
|
|
eabdae |
struct listener {
|
|
|
eabdae |
- int fd, tcpfd, tftpfd, family;
|
|
|
eabdae |
+ int fd, tcpfd, tftpfd, family, used;
|
|
|
eabdae |
+ union mysockaddr addr;
|
|
|
eabdae |
struct irec *iface; /* only sometimes valid for non-wildcard */
|
|
|
eabdae |
struct listener *next;
|
|
|
eabdae |
};
|
|
|
eabdae |
diff --git a/src/network.c b/src/network.c
|
|
|
eabdae |
index d6d4b01..4bbd810 100644
|
|
|
eabdae |
--- a/src/network.c
|
|
|
eabdae |
+++ b/src/network.c
|
|
|
eabdae |
@@ -577,6 +577,56 @@ static void clean_interfaces()
|
|
|
eabdae |
}
|
|
|
eabdae |
}
|
|
|
eabdae |
|
|
|
eabdae |
+/** Release listener if no other interface needs it.
|
|
|
eabdae |
+ *
|
|
|
eabdae |
+ * @return 1 if released, 0 if still required
|
|
|
eabdae |
+ */
|
|
|
eabdae |
+static int release_listener(struct listener *l)
|
|
|
eabdae |
+{
|
|
|
eabdae |
+ if (l->used > 1)
|
|
|
eabdae |
+ {
|
|
|
eabdae |
+ struct irec *iface;
|
|
|
eabdae |
+ for (iface = daemon->interfaces; iface; iface = iface->next)
|
|
|
eabdae |
+ if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
|
|
|
eabdae |
+ {
|
|
|
eabdae |
+ if (iface->found)
|
|
|
eabdae |
+ {
|
|
|
eabdae |
+ /* update listener to point to active interface instead */
|
|
|
eabdae |
+ if (!l->iface->found)
|
|
|
eabdae |
+ l->iface = iface;
|
|
|
eabdae |
+ }
|
|
|
eabdae |
+ else
|
|
|
eabdae |
+ {
|
|
|
eabdae |
+ l->used--;
|
|
|
eabdae |
+ iface->done = 0;
|
|
|
eabdae |
+ }
|
|
|
eabdae |
+ }
|
|
|
eabdae |
+
|
|
|
eabdae |
+ /* Someone is still using this listener, skip its deletion */
|
|
|
eabdae |
+ if (l->used > 0)
|
|
|
eabdae |
+ return 0;
|
|
|
eabdae |
+ }
|
|
|
eabdae |
+
|
|
|
eabdae |
+ if (l->iface->done)
|
|
|
eabdae |
+ {
|
|
|
eabdae |
+ (void)prettyprint_addr(&l->iface->addr, daemon->addrbuff);
|
|
|
eabdae |
+ my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s"),
|
|
|
eabdae |
+ l->iface->name, l->iface->index, daemon->addrbuff);
|
|
|
eabdae |
+ /* In case it ever returns */
|
|
|
eabdae |
+ l->iface->done = 0;
|
|
|
eabdae |
+ }
|
|
|
eabdae |
+
|
|
|
eabdae |
+ if (l->fd != -1)
|
|
|
eabdae |
+ close(l->fd);
|
|
|
eabdae |
+ if (l->tcpfd != -1)
|
|
|
eabdae |
+ close(l->tcpfd);
|
|
|
eabdae |
+ if (l->tftpfd != -1)
|
|
|
eabdae |
+ close(l->tftpfd);
|
|
|
eabdae |
+
|
|
|
eabdae |
+ free(l);
|
|
|
eabdae |
+ return 1;
|
|
|
eabdae |
+}
|
|
|
eabdae |
+
|
|
|
eabdae |
int enumerate_interfaces(int reset)
|
|
|
eabdae |
{
|
|
|
eabdae |
static struct addrlist *spare = NULL;
|
|
|
eabdae |
@@ -684,29 +734,10 @@ int enumerate_interfaces(int reset)
|
|
|
eabdae |
|
|
|
eabdae |
if (!l->iface || l->iface->found)
|
|
|
eabdae |
up = &l->next;
|
|
|
eabdae |
- else
|
|
|
eabdae |
+ else if (release_listener(l))
|
|
|
eabdae |
{
|
|
|
eabdae |
- *up = l->next;
|
|
|
eabdae |
- if (l->iface->done)
|
|
|
eabdae |
- {
|
|
|
eabdae |
- iface = l->iface;
|
|
|
eabdae |
- (void)prettyprint_addr(&iface->addr, daemon->addrbuff);
|
|
|
eabdae |
- my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s"),
|
|
|
eabdae |
- iface->name, iface->index, daemon->addrbuff);
|
|
|
eabdae |
- }
|
|
|
eabdae |
-
|
|
|
eabdae |
- /* In case it ever returns */
|
|
|
eabdae |
- l->iface->done = 0;
|
|
|
eabdae |
-
|
|
|
eabdae |
- if (l->fd != -1)
|
|
|
eabdae |
- close(l->fd);
|
|
|
eabdae |
- if (l->tcpfd != -1)
|
|
|
eabdae |
- close(l->tcpfd);
|
|
|
eabdae |
- if (l->tftpfd != -1)
|
|
|
eabdae |
- close(l->tftpfd);
|
|
|
eabdae |
-
|
|
|
eabdae |
- free(l);
|
|
|
eabdae |
- freed = 1;
|
|
|
eabdae |
+ *up = tmp;
|
|
|
eabdae |
+ freed = 1;
|
|
|
eabdae |
}
|
|
|
eabdae |
}
|
|
|
eabdae |
|
|
|
eabdae |
@@ -959,7 +990,9 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
|
|
|
eabdae |
l->family = addr->sa.sa_family;
|
|
|
eabdae |
l->fd = fd;
|
|
|
eabdae |
l->tcpfd = tcpfd;
|
|
|
eabdae |
- l->tftpfd = tftpfd;
|
|
|
eabdae |
+ l->tftpfd = tftpfd;
|
|
|
eabdae |
+ l->addr = *addr;
|
|
|
eabdae |
+ l->used = 1;
|
|
|
eabdae |
l->iface = NULL;
|
|
|
eabdae |
}
|
|
|
eabdae |
|
|
|
eabdae |
@@ -1000,23 +1033,41 @@ void create_wildcard_listeners(void)
|
|
|
eabdae |
daemon->listeners = l;
|
|
|
eabdae |
}
|
|
|
eabdae |
|
|
|
eabdae |
+static struct listener *find_listener(union mysockaddr *addr)
|
|
|
eabdae |
+{
|
|
|
eabdae |
+ struct listener *l;
|
|
|
eabdae |
+ for (l = daemon->listeners; l; l = l->next)
|
|
|
eabdae |
+ if (sockaddr_isequal(&l->addr, addr))
|
|
|
eabdae |
+ return l;
|
|
|
eabdae |
+ return NULL;
|
|
|
eabdae |
+}
|
|
|
eabdae |
+
|
|
|
eabdae |
void create_bound_listeners(int dienow)
|
|
|
eabdae |
{
|
|
|
eabdae |
struct listener *new;
|
|
|
eabdae |
struct irec *iface;
|
|
|
eabdae |
struct iname *if_tmp;
|
|
|
eabdae |
+ struct listener *existing;
|
|
|
eabdae |
|
|
|
eabdae |
for (iface = daemon->interfaces; iface; iface = iface->next)
|
|
|
eabdae |
- if (!iface->done && !iface->dad && iface->found &&
|
|
|
eabdae |
- (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
|
|
|
eabdae |
+ if (!iface->done && !iface->dad && iface->found)
|
|
|
eabdae |
{
|
|
|
eabdae |
- new->iface = iface;
|
|
|
eabdae |
- new->next = daemon->listeners;
|
|
|
eabdae |
- daemon->listeners = new;
|
|
|
eabdae |
- iface->done = 1;
|
|
|
eabdae |
- (void)prettyprint_addr(&iface->addr, daemon->addrbuff);
|
|
|
eabdae |
- my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s"),
|
|
|
eabdae |
- iface->name, iface->index, daemon->addrbuff);
|
|
|
eabdae |
+ existing = find_listener(&iface->addr);
|
|
|
eabdae |
+ if (existing)
|
|
|
eabdae |
+ {
|
|
|
eabdae |
+ iface->done = 1;
|
|
|
eabdae |
+ existing->used++; /* increase usage counter */
|
|
|
eabdae |
+ }
|
|
|
eabdae |
+ else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
|
|
|
eabdae |
+ {
|
|
|
eabdae |
+ new->iface = iface;
|
|
|
eabdae |
+ new->next = daemon->listeners;
|
|
|
eabdae |
+ daemon->listeners = new;
|
|
|
eabdae |
+ iface->done = 1;
|
|
|
eabdae |
+ (void)prettyprint_addr(&iface->addr, daemon->addrbuff);
|
|
|
eabdae |
+ my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s"),
|
|
|
eabdae |
+ iface->name, iface->index, daemon->addrbuff);
|
|
|
eabdae |
+ }
|
|
|
eabdae |
}
|
|
|
eabdae |
|
|
|
eabdae |
/* Check for --listen-address options that haven't been used because there's
|
|
|
eabdae |
--
|
|
|
eabdae |
2.20.1
|
|
|
eabdae |
|