import dnsmasq-2.79-13.el8

This commit is contained in:
CentOS Sources 2020-07-28 05:09:49 -04:00 committed by Stepan Oksanichenko
parent 71c5ec5eae
commit f43f6cf17c
8 changed files with 1852 additions and 1 deletions

View File

@ -0,0 +1,47 @@
From 69bc94779c2f035a9fffdb5327a54c3aeca73ed5 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Wed, 14 Aug 2019 20:44:50 +0100
Subject: [PATCH] Fix memory leak in helper.c
Thanks to Xu Mingjie <xumingjie1995@outlook.com> for spotting this.
---
src/helper.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/helper.c b/src/helper.c
index 33ba120..c392eec 100644
--- a/src/helper.c
+++ b/src/helper.c
@@ -80,7 +80,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
pid_t pid;
int i, pipefd[2];
struct sigaction sigact;
-
+ unsigned char *alloc_buff = NULL;
+
/* create the pipe through which the main program sends us commands,
then fork our process. */
if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
@@ -186,11 +187,16 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
struct script_data data;
char *p, *action_str, *hostname = NULL, *domain = NULL;
unsigned char *buf = (unsigned char *)daemon->namebuff;
- unsigned char *end, *extradata, *alloc_buff = NULL;
+ unsigned char *end, *extradata;
int is6, err = 0;
int pipeout[2];
- free(alloc_buff);
+ /* Free rarely-allocated memory from previous iteration. */
+ if (alloc_buff)
+ {
+ free(alloc_buff);
+ alloc_buff = NULL;
+ }
/* we read zero bytes when pipe closed: this is our signal to exit */
if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1))
--
1.7.10.4

View File

@ -0,0 +1,317 @@
From 653481c6ebf46dcadb5a017085325d956dd04a28 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 21 Aug 2018 22:06:36 +0100
Subject: [PATCH] Properly deal with unaligned addresses in DHCPv6 packets.
Thanks to Vladislav Grishenko for spotting this.
(cherry picked from commit 97f876b64c22b2b18412e2e3d8506ee33e42db7c)
Conflicts:
src/rfc3315.c
---
src/rfc1035.c | 2 +-
src/rfc3315.c | 101 ++++++++++++++++++++++++++++++++++------------------------
2 files changed, 61 insertions(+), 42 deletions(-)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 6b3bb27..ee5f7a0 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1376,7 +1376,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
t->class, C_IN, "t", t->len, t->txt))
- anscount ++;
+ anscount++;
}
}
diff --git a/src/rfc3315.c b/src/rfc3315.c
index 21fcd9b..ee1cf17 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -639,9 +639,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
int plain_range = 1;
u32 lease_time;
struct dhcp_lease *ltmp;
- struct in6_addr *req_addr;
- struct in6_addr addr;
-
+ struct in6_addr req_addr, addr;
+
if (!check_ia(state, opt, &ia_end, &ia_option))
continue;
@@ -709,9 +708,10 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
- req_addr = opt6_ptr(ia_option, 0);
+ /* worry about alignment here. */
+ memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
- if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
+ if ((c = address6_valid(state->context, &req_addr, solicit_tags, plain_range)))
{
lease_time = c->lease_time;
/* If the client asks for an address on the same network as a configured address,
@@ -719,14 +719,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
addresses automatic. */
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
{
- req_addr = &addr;
+ req_addr = addr;
mark_config_used(c, &addr);
if (have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
}
- else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
+ else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
continue; /* not an address we're allowed */
- else if (!check_address(state, req_addr))
+ else if (!check_address(state, &req_addr))
continue; /* address leased elsewhere */
/* add address to output packet */
@@ -734,8 +734,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
- add_address(state, c, lease_time, ia_option, &min_time, req_addr, now);
- mark_context_used(state, req_addr);
+ add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
+ mark_context_used(state, &req_addr);
get_context_tag(state, c);
address_assigned = 1;
}
@@ -768,15 +768,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ltmp = NULL;
while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
{
- req_addr = &ltmp->addr6;
- if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
+ req_addr = ltmp->addr6;
+ if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
{
#ifdef OPTION6_PREFIX_CLASS
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
- add_address(state, c, c->lease_time, NULL, &min_time, req_addr, now);
- mark_context_used(state, req_addr);
+ add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
+ mark_context_used(state, &req_addr);
get_context_tag(state, c);
address_assigned = 1;
}
@@ -892,16 +892,19 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
- struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
+ struct in6_addr req_addr;
struct dhcp_context *dynamic, *c;
unsigned int lease_time;
struct in6_addr addr;
int config_ok = 0;
+
+ /* align. */
+ memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
- if ((c = address6_valid(state->context, req_addr, tagif, 1)))
- config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
+ if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
+ config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr);
- if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
+ if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
{
if (!dynamic && !config_ok)
{
@@ -911,7 +914,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
put_opt6_string(_("address unavailable"));
end_opt6(o1);
}
- else if (!check_address(state, req_addr))
+ else if (!check_address(state, &req_addr))
{
/* Address leased to another DUID/IAID */
o1 = new_opt6(OPTION6_STATUS_CODE);
@@ -933,7 +936,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
state->send_prefix_class = prefix_class_from_context(c);
#endif
- add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
+ add_address(state, dynamic, lease_time, ia_option, &min_time, &req_addr, now);
get_context_tag(state, dynamic);
address_assigned = 1;
}
@@ -996,15 +999,17 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease = NULL;
- struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
+ struct in6_addr req_addr;
unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
unsigned int valid_time = opt6_uint(ia_option, 20, 4);
char *message = NULL;
struct dhcp_context *this_context;
+
+ memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if (!(lease = lease6_find(state->clid, state->clid_len,
state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
- state->iaid, req_addr)))
+ state->iaid, &req_addr)))
{
/* If the server cannot find a client entry for the IA the server
returns the IA containing no addresses with a Status Code option set
@@ -1012,7 +1017,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
save_counter(iacntr);
t1cntr = 0;
- log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
+ log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOBINDING);
@@ -1024,15 +1029,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
- if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
- (this_context = address6_valid(state->context, req_addr, tagif, 1)))
+ if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
+ (this_context = address6_valid(state->context, &req_addr, tagif, 1)))
{
struct in6_addr addr;
unsigned int lease_time;
get_context_tag(state, this_context);
- if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
+ if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr) && have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
else
lease_time = this_context->lease_time;
@@ -1045,7 +1050,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
if (state->ia_type == OPTION6_IA_NA && state->hostname)
{
- char *addr_domain = get_domain6(req_addr);
+ char *addr_domain = get_domain6(&req_addr);
if (!state->send_domain)
state->send_domain = addr_domain;
lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
@@ -1063,12 +1068,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
if (message && (message != state->hostname))
- log6_packet(state, "DHCPREPLY", req_addr, message);
+ log6_packet(state, "DHCPREPLY", &req_addr, message);
else
- log6_quiet(state, "DHCPREPLY", req_addr, message);
+ log6_quiet(state, "DHCPREPLY", &req_addr, message);
o1 = new_opt6(OPTION6_IAADDR);
- put_opt6(req_addr, sizeof(*req_addr));
+ put_opt6(&req_addr, sizeof(req_addr));
put_opt6_long(preferred_time);
put_opt6_long(valid_time);
end_opt6(o1);
@@ -1100,19 +1105,23 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option;
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
- struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
+ struct in6_addr req_addr;
+
+ /* alignment */
+ memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
- if (!address6_valid(state->context, req_addr, tagif, 1))
+ if (!address6_valid(state->context, &req_addr, tagif, 1))
{
o1 = new_opt6(OPTION6_STATUS_CODE);
put_opt6_short(DHCP6NOTONLINK);
put_opt6_string(_("confirm failed"));
end_opt6(o1);
+ log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
return 1;
}
good_addr = 1;
- log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
+ log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
}
}
@@ -1171,9 +1180,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease;
-
+ struct in6_addr addr;
+
+ /* align */
+ memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
- state->iaid, opt6_ptr(ia_option, 0))))
+ state->iaid, &addr)))
lease_prune(lease, now);
else
{
@@ -1233,12 +1245,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
{
struct dhcp_lease *lease;
- struct in6_addr *addrp = opt6_ptr(ia_option, 0);
+ struct in6_addr addr;
- if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, addrp))
+ /* align */
+ memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
+
+ if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, &addr))
{
prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
- inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
+ inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
daemon->addrbuff, daemon->dhcp_buff3);
config->flags |= CONFIG_DECLINED;
@@ -1250,7 +1265,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
context_tmp->addr_epoch++;
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
- state->iaid, opt6_ptr(ia_option, 0))))
+ state->iaid, &addr)))
lease_prune(lease, now);
else
{
@@ -1267,7 +1282,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
o1 = new_opt6(OPTION6_IAADDR);
- put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
+ put_opt6(&addr, IN6ADDRSZ);
put_opt6_long(0);
put_opt6_long(0);
end_opt6(o1);
@@ -1935,7 +1950,11 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
}
else if (type == OPTION6_IAADDR)
{
- inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
+ struct in6_addr addr;
+
+ /* align */
+ memcpy(&addr, opt6_ptr(opt, 0), IN6ADDRSZ);
+ inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
sprintf(daemon->namebuff, "%s PL=%u VL=%u",
daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
optname = "iaaddr";
--
1.8.3.1

View File

@ -0,0 +1,44 @@
From 6307208c806f9b968eca178931b3d77c4ed83c54 Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
Date: Fri, 6 Mar 2020 15:37:23 +0100
Subject: [PATCH] Correct range check of dhcp-host prefix
It incorrectly works with 32 bit integer only when counting number of
addresses in range. It works correctly only between prefixlen 96 and
128. Use 64bit shift to work with well with numbers higher than 64.
Fixes commit 79aba0f10ad0157fb4f48afbbcb03f094caff97a error.
---
src/option.c | 2 +-
src/rfc3315.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/option.c b/src/option.c
index 88cd2ab..79122df 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3247,7 +3247,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (!atoi_check(pref, &new_addr->prefixlen) ||
new_addr->prefixlen > 128 ||
- (((1<<(128-new_addr->prefixlen))-1) & addrpart) != 0)
+ ((((u64)1<<(128-new_addr->prefixlen))-1) & addrpart) != 0)
{
dhcp_config_free(new);
ret_err(_("bad IPv6 prefix"));
diff --git a/src/rfc3315.c b/src/rfc3315.c
index a0067e9..f59aedc 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -1798,7 +1798,7 @@ static int config_valid(struct dhcp_config *config, struct dhcp_context *context
addresses = 1;
if (addr_list->flags & ADDRLIST_PREFIX)
- addresses = 1<<(128-addr_list->prefixlen);
+ addresses = (u64)1<<(128-addr_list->prefixlen);
if ((addr_list->flags & ADDRLIST_WILDCARD))
{
--
2.21.1

View File

@ -0,0 +1,132 @@
commit 98c6998116e33f9f34b798682e0695f4166bd86d
Author: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon Mar 2 17:10:25 2020 +0000
Optimise closing file descriptors.
Dnsmasq needs to close all the file descriptors it inherits, for security
reasons. This is traditionally done by calling close() on every possible
file descriptor (most of which won't be open.) On big servers where
"every possible file descriptor" is a rather large set, this gets
rather slow, so we use the /proc/<pid>/fd directory to get a list
of the fds which are acually open.
This only works on Linux. On other platforms, and on Linux systems
without a /proc filesystem, we fall back to the old way.
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 573aac0..10f19ea 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -138,20 +138,18 @@ int main (int argc, char **argv)
}
#endif
- /* Close any file descriptors we inherited apart from std{in|out|err}
-
- Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
+ /* Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
otherwise file descriptors we create can end up being 0, 1, or 2
and then get accidentally closed later when we make 0, 1, and 2
open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
but it's not guaranteed. By opening /dev/null three times, we
ensure that we're not using those fds for real stuff. */
- for (i = 0; i < max_fd; i++)
- if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
- close(i);
- else
- open("/dev/null", O_RDWR);
-
+ for (i = 0; i < 3; i++)
+ open("/dev/null", O_RDWR);
+
+ /* Close any file descriptors we inherited apart from std{in|out|err} */
+ close_fds(max_fd, -1, -1, -1);
+
#ifndef HAVE_LINUX_NETWORK
# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
if (!option_bool(OPT_NOWILD))
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 6103eb5..c46bfeb 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1283,7 +1283,7 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len,
int expand_buf(struct iovec *iov, size_t size);
char *print_mac(char *buff, unsigned char *mac, int len);
int read_write(int fd, unsigned char *packet, int size, int rw);
-
+void close_fds(long max_fd, int spare1, int spare2, int spare3);
int wildcard_match(const char* wildcard, const char* match);
int wildcard_matchn(const char* wildcard, const char* match, int num);
diff --git a/src/helper.c b/src/helper.c
index 1b260a1..7072cf4 100644
--- a/src/helper.c
+++ b/src/helper.c
@@ -131,12 +131,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
Don't close err_fd, in case the lua-init fails.
Note that we have to do this before lua init
so we don't close any lua fds. */
- for (max_fd--; max_fd >= 0; max_fd--)
- if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO &&
- max_fd != STDIN_FILENO && max_fd != pipefd[0] &&
- max_fd != event_fd && max_fd != err_fd)
- close(max_fd);
-
+ close_fds(max_fd, pipefd[0], event_fd, err_fd);
+
#ifdef HAVE_LUASCRIPT
if (daemon->luascript)
{
diff --git a/src/util.c b/src/util.c
index 73bf62a..f058c92 100644
--- a/src/util.c
+++ b/src/util.c
@@ -705,6 +705,47 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
return 1;
}
+/* close all fds except STDIN, STDOUT and STDERR, spare1, spare2 and spare3 */
+void close_fds(long max_fd, int spare1, int spare2, int spare3)
+{
+ /* On Linux, use the /proc/ filesystem to find which files
+ are actually open, rather than iterate over the whole space,
+ for efficiency reasons. If this fails we drop back to the dumb code. */
+#ifdef HAVE_LINUX_NETWORK
+ DIR *d;
+
+ if ((d = opendir("/proc/self/fd")))
+ {
+ struct dirent *de;
+
+ while ((de = readdir(d)))
+ {
+ long fd;
+ char *e = NULL;
+
+ errno = 0;
+ fd = strtol(de->d_name, &e, 10);
+
+ if (errno != 0 || !e || *e || fd == dirfd(d) ||
+ fd == STDOUT_FILENO || fd == STDERR_FILENO || fd == STDIN_FILENO ||
+ fd == spare1 || fd == spare2 || fd == spare3)
+ continue;
+
+ close(fd);
+ }
+
+ closedir(d);
+ return;
+ }
+#endif
+
+ /* fallback, dumb code. */
+ for (max_fd--; max_fd >= 0; max_fd--)
+ if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && max_fd != STDIN_FILENO &&
+ max_fd != spare1 && max_fd != spare2 && max_fd != spare3)
+ close(max_fd);
+}
+
/* Basically match a string value against a wildcard pattern. */
int wildcard_match(const char* wildcard, const char* match)
{

View File

@ -0,0 +1,895 @@
From 9b200103342c0909def9f8d9b97cfd889be6bfd8 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Mon, 3 Feb 2020 23:58:45 +0000
Subject: [PATCH] Support prefixed ranges of ipv6 addresses in dhcp-host.
When a request matching the clid or mac address is
recieved the server will iterate over all candidate
addresses until it find's one that is not already
leased to a different clid/iaid and advertise
this address.
Using multiple reservations for a single host makes it
possible to maintain a static leases only configuration
which support network booting systems with UEFI firmware
that request a new address (a new SOLICIT with a new IA_NA
option using a new IAID) for different boot modes, for
instance 'PXE over IPv6', and 'HTTP-Boot over IPv6'. Open
Virtual Machine Firmware (OVMF) and most UEFI firmware
build on the EDK2 code base exhibit this behaviour.
(cherry picked from commit 79aba0f10ad0157fb4f48afbbcb03f094caff97a)
Conflicts:
CHANGELOG
src/dhcp-common.c
src/dnsmasq.h
src/dhcp6.c
Extend 79aba0f10ad0157fb4f48afbbcb03f094caff97a for multiple IPv6 addresses.
(cherry picked from commit 137286e9baecf6a3ba97722ef1b49c851b531810)
Conflicts:
man/dnsmasq.8
src/dhcp-common.c
src/dhcp6.c
src/rfc3315.c
src/option.c
Fix bug with prefixed wildcard addresses in 137286e9baecf6a3ba97722ef1b49c851b531810
(cherry picked from commit f064188032a829efdcf3988b24ac795ff52785ec)
Conflicts:
src/rfc3315.c
---
man/dnsmasq.8 | 13 +-
src/dhcp-common.c | 56 +++++---
src/dhcp6.c | 51 +++----
src/dnsmasq.h | 17 +--
src/option.c | 402 ++++++++++++++++++++++++++++++------------------------
src/rfc3315.c | 83 ++++++++++-
6 files changed, 370 insertions(+), 252 deletions(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index f52762f..2c9d9f6 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -985,13 +985,20 @@ allowed to specify the client ID as text, like this:
.B --dhcp-host=id:clientidastext,.....
A single
-.B dhcp-host
-may contain an IPv4 address or an IPv6 address, or both. IPv6 addresses must be bracketed by square brackets thus:
+.B --dhcp-host
+may contain an IPv4 address or one or more IPv6 addresses, or both. IPv6 addresses must be bracketed by square brackets thus:
.B --dhcp-host=laptop,[1234::56]
IPv6 addresses may contain only the host-identifier part:
.B --dhcp-host=laptop,[::56]
in which case they act as wildcards in constructed dhcp ranges, with
-the appropriate network part inserted.
+the appropriate network part inserted. For IPv6, an address may include a prefix length:
+.B --dhcp-host=laptop,[1234:50/126]
+which (in this case) specifies four addresses, 1234::50 to 1234::53. This (an the ability
+to specify multiple addresses) is useful
+when a host presents either a consistent name or hardware-ID, but varying DUIDs, since it allows
+dnsmasq to honour the static address allocation but assign a different adddress for each DUID. This
+typically occurs when chain netbooting, as each stage of the chain gets in turn allocates an address.
+
Note that in IPv6 DHCP, the hardware address may not be
available, though it normally is for direct-connected clients, or
clients using DHCP relays which support RFC 6939.
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index d9719d1..5d437dd 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -271,26 +271,35 @@ static int is_config_in_context(struct dhcp_context *context, struct dhcp_config
{
if (!context) /* called via find_config() from lease_update_from_configs() */
return 1;
-
- if (!(config->flags & (CONFIG_ADDR | CONFIG_ADDR6)))
- return 1;
#ifdef HAVE_DHCP6
- if ((context->flags & CONTEXT_V6) && (config->flags & CONFIG_WILDCARD))
- return 1;
-#endif
+ if (context->flags & CONTEXT_V6)
+ {
+ struct addrlist *addr_list;
- for (; context; context = context->current)
-#ifdef HAVE_DHCP6
- if (context->flags & CONTEXT_V6)
- {
- if ((config->flags & CONFIG_ADDR6) && is_same_net6(&config->addr6, &context->start6, context->prefix))
- return 1;
- }
- else
+ if (!(config->flags & CONFIG_ADDR6))
+ return 1;
+
+ for (; context; context = context->current)
+ for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
+ {
+ if ((addr_list->flags & ADDRLIST_WILDCARD) && context->prefix == 64)
+ return 1;
+
+ if (is_same_net6(&addr_list->addr.addr.addr6, &context->start6, context->prefix))
+ return 1;
+ }
+ }
+ else
#endif
- if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
+ {
+ if (!(config->flags & CONFIG_ADDR))
return 1;
+
+ for (; context; context = context->current)
+ if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
+ return 1;
+ }
return 0;
}
@@ -418,10 +427,21 @@ void dhcp_update_configs(struct dhcp_config *configs)
#ifdef HAVE_DHCP6
if (prot == AF_INET6 &&
- (!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
+ (!(conf_tmp = config_find_by_address6(configs, NULL, 0, &crec->addr.addr.addr.addr6)) || conf_tmp == config))
{
- memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
- config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
+ /* host must have exactly one address if comming from /etc/hosts. */
+ if (!config->addr6 && (config->addr6 = whine_malloc(sizeof(struct addrlist))))
+ {
+ config->addr6->next = NULL;
+ config->addr6->flags = 0;
+ }
+
+ if (config->addr6 && !config->addr6->next && !(config->addr6->flags & (ADDRLIST_WILDCARD|ADDRLIST_PREFIX)))
+ {
+ memcpy(&config->addr6->addr.addr.addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
+ config->flags |= CONFIG_ADDR6 | CONFIG_ADDR6_HOSTS;
+ }
+
continue;
}
#endif
diff --git a/src/dhcp6.c b/src/dhcp6.c
index 0853664..6f1f54e 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -384,21 +384,26 @@ static int complete_context6(struct in6_addr *local, int prefix,
return 1;
}
-struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, u64 addr)
+struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, struct in6_addr *addr)
{
struct dhcp_config *config;
for (config = configs; config; config = config->next)
- if ((config->flags & CONFIG_ADDR6) &&
- is_same_net6(&config->addr6, net, prefix) &&
- (prefix == 128 || addr6part(&config->addr6) == addr))
- return config;
+ if (config->flags & CONFIG_ADDR6)
+ {
+ struct addrlist *addr_list;
+
+ for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
+ if ((!net || is_same_net6(&addr_list->addr.addr.addr6, net, prefix) || ((addr_list->flags & ADDRLIST_WILDCARD) && prefix == 64)) &&
+ is_same_net6(&addr_list->addr.addr.addr6, addr, (addr_list->flags & ADDRLIST_PREFIX) ? addr_list->prefixlen : 128))
+ return config;
+ }
return NULL;
}
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
- int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
+ unsigned int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
@@ -453,16 +458,15 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
for (d = context; d; d = d->current)
if (addr == addr6part(&d->local6))
break;
+
+ *ans = c->start6;
+ setaddr6part (ans, addr);
if (!d &&
!lease6_find_by_addr(&c->start6, c->prefix, addr) &&
- !config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, addr))
- {
- *ans = c->start6;
- setaddr6part (ans, addr);
- return c;
- }
-
+ !config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, ans))
+ return c;
+
addr++;
if (addr == addr6part(&c->end6) + 1)
@@ -516,27 +520,6 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
return NULL;
}
-int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
-{
- if (!config || !(config->flags & CONFIG_ADDR6))
- return 0;
-
- if ((config->flags & CONFIG_WILDCARD) && context->prefix == 64)
- {
- *addr = context->start6;
- setaddr6part(addr, addr6part(&config->addr6));
- return 1;
- }
-
- if (is_same_net6(&context->start6, &config->addr6, context->prefix))
- {
- *addr = config->addr6;
- return 1;
- }
-
- return 0;
-}
-
void make_duid(time_t now)
{
(void)now;
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 6b18bb7..9437226 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -343,9 +343,11 @@ struct ds_config {
struct ds_config *next;
};
-#define ADDRLIST_LITERAL 1
-#define ADDRLIST_IPV6 2
-#define ADDRLIST_REVONLY 4
+#define ADDRLIST_LITERAL 1
+#define ADDRLIST_IPV6 2
+#define ADDRLIST_REVONLY 4
+#define ADDRLIST_PREFIX 8
+#define ADDRLIST_WILDCARD 16
struct addrlist {
struct all_addr addr;
@@ -748,7 +750,7 @@ struct dhcp_config {
char *hostname, *domain;
struct dhcp_netid_list *netid;
#ifdef HAVE_DHCP6
- struct in6_addr addr6;
+ struct addrlist *addr6;
#endif
struct in_addr addr;
time_t decline_time;
@@ -770,7 +772,7 @@ struct dhcp_config {
#define CONFIG_DECLINED 1024 /* address declined by client */
#define CONFIG_BANK 2048 /* from dhcp hosts file */
#define CONFIG_ADDR6 4096
-#define CONFIG_WILDCARD 8192
+#define CONFIG_ADDR6_HOSTS 16384 /* address added by from /etc/hosts */
struct dhcp_opt {
int opt, len, flags;
@@ -1463,8 +1465,7 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
void dhcp6_init(void);
void dhcp6_packet(time_t now);
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
- int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
-int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
+ unsigned int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
struct dhcp_context *address6_available(struct dhcp_context *context,
struct in6_addr *taddr,
struct dhcp_netid *netids,
@@ -1474,7 +1475,7 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
struct dhcp_netid *netids,
int plain_range);
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net,
- int prefix, u64 addr);
+ int prefix, struct in6_addr *addr);
void make_duid(time_t now);
void dhcp_construct_contexts(time_t now);
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
diff --git a/src/option.c b/src/option.c
index b12183b..ea70ee3 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1010,15 +1010,30 @@ static void dhcp_config_free(struct dhcp_config *config)
if (config)
{
struct hwaddr_config *hwaddr = config->hwaddr;
+
while (hwaddr)
{
struct hwaddr_config *tmp = hwaddr;
hwaddr = hwaddr->next;
free(tmp);
}
+
dhcp_netid_list_free(config->netid);
+
if (config->flags & CONFIG_CLID)
free(config->clid);
+
+ if (config->flags & CONFIG_ADDR6)
+ {
+ struct addrlist *addr, *tmp;
+
+ for (addr = config->addr6; addr; addr = tmp)
+ {
+ tmp = addr->next;
+ free(addr);
+ }
+ }
+
free(config);
}
}
@@ -3143,8 +3158,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_BANK:
case 'G': /* --dhcp-host */
{
- int j, k = 0;
- char *a[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
struct dhcp_config *new;
struct in_addr in;
@@ -3155,197 +3168,222 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->hwaddr = NULL;
new->netid = NULL;
new->clid = NULL;
+ new->addr6 = NULL;
- if ((a[0] = arg))
- for (k = 1; k < 7; k++)
- if (!(a[k] = split(a[k-1])))
- break;
-
- for (j = 0; j < k; j++)
- if (strchr(a[j], ':')) /* ethernet address, netid or binary CLID */
- {
- char *arg = a[j];
-
- if ((arg[0] == 'i' || arg[0] == 'I') &&
- (arg[1] == 'd' || arg[1] == 'D') &&
- arg[2] == ':')
- {
- if (arg[3] == '*')
- new->flags |= CONFIG_NOCLID;
- else
- {
- int len;
- arg += 3; /* dump id: */
- if (strchr(arg, ':'))
- len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
- else
- {
- unhide_metas(arg);
- len = (int) strlen(arg);
- }
-
- if (len == -1)
- {
- dhcp_config_free(new);
- ret_err(_("bad hex constant"));
- }
- else if ((new->clid = opt_malloc(len)))
- {
- new->flags |= CONFIG_CLID;
- new->clid_len = len;
- memcpy(new->clid, arg, len);
- }
- }
- }
- /* dhcp-host has strange backwards-compat needs. */
- else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
- {
- struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
- newlist->next = new->netid;
- new->netid = newlist;
- newlist->list = dhcp_netid_create(arg+4, NULL);
- }
- else if (strstr(arg, "tag:") == arg)
- {
-
- dhcp_config_free(new);
- ret_err(_("cannot match tags in --dhcp-host"));
- }
+ while (arg)
+ {
+ comma = split(arg);
+ if (strchr(arg, ':')) /* ethernet address, netid or binary CLID */
+ {
+ if ((arg[0] == 'i' || arg[0] == 'I') &&
+ (arg[1] == 'd' || arg[1] == 'D') &&
+ arg[2] == ':')
+ {
+ if (arg[3] == '*')
+ new->flags |= CONFIG_NOCLID;
+ else
+ {
+ int len;
+ arg += 3; /* dump id: */
+ if (strchr(arg, ':'))
+ len = parse_hex(arg, (unsigned char *)arg, -1, NULL, NULL);
+ else
+ {
+ unhide_metas(arg);
+ len = (int) strlen(arg);
+ }
+
+ if (len == -1)
+ {
+ dhcp_config_free(new);
+ ret_err(_("bad hex constant"));
+ }
+ else if ((new->clid = opt_malloc(len)))
+ {
+ new->flags |= CONFIG_CLID;
+ new->clid_len = len;
+ memcpy(new->clid, arg, len);
+ }
+ }
+ }
+ /* dhcp-host has strange backwards-compat needs. */
+ else if (strstr(arg, "net:") == arg || strstr(arg, "set:") == arg)
+ {
+ struct dhcp_netid_list *newlist = opt_malloc(sizeof(struct dhcp_netid_list));
+ newlist->next = new->netid;
+ new->netid = newlist;
+ newlist->list = dhcp_netid_create(arg+4, NULL);
+ }
+ else if (strstr(arg, "tag:") == arg)
+ {
+
+ dhcp_config_free(new);
+ ret_err(_("cannot match tags in --dhcp-host"));
+ }
#ifdef HAVE_DHCP6
- else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
- {
- arg[strlen(arg)-1] = 0;
- arg++;
-
- if (!inet_pton(AF_INET6, arg, &new->addr6))
- {
- dhcp_config_free(new);
- ret_err(_("bad IPv6 address"));
- }
-
- for (i= 0; i < 8; i++)
- if (new->addr6.s6_addr[i] != 0)
- break;
+ else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
+ {
+ char *pref;
+ struct in6_addr in6;
+ struct addrlist *new_addr;
+
+ arg[strlen(arg)-1] = 0;
+ arg++;
+ pref = split_chr(arg, '/');
+
+ if (!inet_pton(AF_INET6, arg, &in6))
+ {
+ dhcp_config_free(new);
+ ret_err(_("bad IPv6 address"));
+ }
- /* set WILDCARD if network part all zeros */
- if (i == 8)
- new->flags |= CONFIG_WILDCARD;
+ new_addr = opt_malloc(sizeof(struct addrlist));
+ new_addr->next = new->addr6;
+ new_addr->flags = 0;
+ new_addr->addr.addr.addr6 = in6;
+ new->addr6 = new_addr;
+
+ if (pref)
+ {
+ u64 addrpart = addr6part(&in6);
+
+ if (!atoi_check(pref, &new_addr->prefixlen) ||
+ new_addr->prefixlen > 128 ||
+ (((1<<(128-new_addr->prefixlen))-1) & addrpart) != 0)
+ {
+ dhcp_config_free(new);
+ ret_err(_("bad IPv6 prefix"));
+ }
+
+ new_addr->flags |= ADDRLIST_PREFIX;
+ }
- new->flags |= CONFIG_ADDR6;
- }
+ for (i= 0; i < 8; i++)
+ if (in6.s6_addr[i] != 0)
+ break;
+
+ /* set WILDCARD if network part all zeros */
+ if (i == 8)
+ new_addr->flags |= ADDRLIST_WILDCARD;
+
+ new->flags |= CONFIG_ADDR6;
+ }
#endif
- else
- {
- struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
- if ((newhw->hwaddr_len = parse_hex(a[j], newhw->hwaddr, DHCP_CHADDR_MAX,
- &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
- {
- free(newhw);
- dhcp_config_free(new);
- ret_err(_("bad hex constant"));
- }
- else
- {
- newhw->next = new->hwaddr;
- new->hwaddr = newhw;
- }
- }
- }
- else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
- {
- struct dhcp_config *configs;
-
- new->addr = in;
- new->flags |= CONFIG_ADDR;
-
- /* If the same IP appears in more than one host config, then DISCOVER
- for one of the hosts will get the address, but REQUEST will be NAKed,
- since the address is reserved by the other one -> protocol loop. */
- for (configs = daemon->dhcp_conf; configs; configs = configs->next)
- if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
+ else
{
- sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
- return 0;
- }
- }
- else
- {
- char *cp, *lastp = NULL, last = 0;
- int fac = 1, isdig = 0;
-
- if (strlen(a[j]) > 1)
- {
- lastp = a[j] + strlen(a[j]) - 1;
- last = *lastp;
- switch (last)
+ struct hwaddr_config *newhw = opt_malloc(sizeof(struct hwaddr_config));
+ if ((newhw->hwaddr_len = parse_hex(arg, newhw->hwaddr, DHCP_CHADDR_MAX,
+ &newhw->wildcard_mask, &newhw->hwaddr_type)) == -1)
+ {
+ free(newhw);
+ dhcp_config_free(new);
+ ret_err(_("bad hex constant"));
+ }
+ else
+ {
+ newhw->next = new->hwaddr;
+ new->hwaddr = newhw;
+ }
+ }
+ }
+ else if (strchr(arg, '.') && (inet_pton(AF_INET, arg, &in) > 0))
+ {
+ struct dhcp_config *configs;
+
+ new->addr = in;
+ new->flags |= CONFIG_ADDR;
+
+ /* If the same IP appears in more than one host config, then DISCOVER
+ for one of the hosts will get the address, but REQUEST will be NAKed,
+ since the address is reserved by the other one -> protocol loop. */
+ for (configs = daemon->dhcp_conf; configs; configs = configs->next)
+ if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
{
- case 'w':
- case 'W':
- fac *= 7;
- /* fall through */
- case 'd':
- case 'D':
- fac *= 24;
- /* fall through */
- case 'h':
- case 'H':
- fac *= 60;
- /* fall through */
- case 'm':
- case 'M':
- fac *= 60;
- /* fall through */
- case 's':
- case 'S':
- *lastp = 0;
- }
- }
-
- for (cp = a[j]; *cp; cp++)
- if (isdigit((unsigned char)*cp))
- isdig = 1;
- else if (*cp != ' ')
- break;
+ sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in));
+ return 0;
+ }
+ }
+ else
+ {
+ char *cp, *lastp = NULL, last = 0;
+ int fac = 1, isdig = 0;
+
+ if (strlen(arg) > 1)
+ {
+ lastp = arg + strlen(arg) - 1;
+ last = *lastp;
+ switch (last)
+ {
+ case 'w':
+ case 'W':
+ fac *= 7;
+ /* fall through */
+ case 'd':
+ case 'D':
+ fac *= 24;
+ /* fall through */
+ case 'h':
+ case 'H':
+ fac *= 60;
+ /* fall through */
+ case 'm':
+ case 'M':
+ fac *= 60;
+ /* fall through */
+ case 's':
+ case 'S':
+ *lastp = 0;
+ }
+ }
+
+ for (cp = arg; *cp; cp++)
+ if (isdigit((unsigned char)*cp))
+ isdig = 1;
+ else if (*cp != ' ')
+ break;
+
+ if (*cp)
+ {
+ if (lastp)
+ *lastp = last;
+ if (strcmp(arg, "infinite") == 0)
+ {
+ new->lease_time = 0xffffffff;
+ new->flags |= CONFIG_TIME;
+ }
+ else if (strcmp(arg, "ignore") == 0)
+ new->flags |= CONFIG_DISABLE;
+ else
+ {
+ if (!(new->hostname = canonicalise_opt(arg)) ||
+ !legal_hostname(new->hostname))
+ {
+ dhcp_config_free(new);
+ ret_err(_("bad DHCP host name"));
+ }
+
+ new->flags |= CONFIG_NAME;
+ new->domain = strip_hostname(new->hostname);
+ }
+ }
+ else if (isdig)
+ {
+ new->lease_time = atoi(arg) * fac;
+ /* Leases of a minute or less confuse
+ some clients, notably Apple's */
+ if (new->lease_time < 120)
+ new->lease_time = 120;
+ new->flags |= CONFIG_TIME;
+ }
+ }
+
+ arg = comma;
+ }
- if (*cp)
- {
- if (lastp)
- *lastp = last;
- if (strcmp(a[j], "infinite") == 0)
- {
- new->lease_time = 0xffffffff;
- new->flags |= CONFIG_TIME;
- }
- else if (strcmp(a[j], "ignore") == 0)
- new->flags |= CONFIG_DISABLE;
- else
- {
- if (!(new->hostname = canonicalise_opt(a[j])) ||
- !legal_hostname(new->hostname))
- {
- dhcp_config_free(new);
- ret_err(_("bad DHCP host name"));
- }
-
- new->flags |= CONFIG_NAME;
- new->domain = strip_hostname(new->hostname);
- }
- }
- else if (isdig)
- {
- new->lease_time = atoi(a[j]) * fac;
- /* Leases of a minute or less confuse
- some clients, notably Apple's */
- if (new->lease_time < 120)
- new->lease_time = 120;
- new->flags |= CONFIG_TIME;
- }
- }
-
daemon->dhcp_conf = new;
break;
}
-
+
case LOPT_TAG_IF: /* --tag-if */
{
struct tag_if *new = opt_malloc(sizeof(struct tag_if));
diff --git a/src/rfc3315.c b/src/rfc3315.c
index ee1cf17..ee58b57 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -55,6 +55,8 @@ static struct prefix_class *prefix_class_from_context(struct dhcp_context *conte
static void mark_context_used(struct state *state, struct in6_addr *addr);
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
static int check_address(struct state *state, struct in6_addr *addr);
+static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state);
+static int config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
unsigned int *min_time, struct in6_addr *addr, time_t now);
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
@@ -717,7 +719,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
/* If the client asks for an address on the same network as a configured address,
offer the configured address instead, to make moving to newly-configured
addresses automatic. */
- if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
+ if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state))
{
req_addr = addr;
mark_config_used(c, &addr);
@@ -745,8 +747,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
for (c = state->context; c; c = c->current)
if (!(c->flags & CONTEXT_CONF_USED) &&
match_netid(c->filter, solicit_tags, plain_range) &&
- config_valid(config, c, &addr) &&
- check_address(state, &addr))
+ config_valid(config, c, &addr, state))
{
mark_config_used(state->context, &addr);
if (have_config(config, CONFIG_TIME))
@@ -895,14 +896,13 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
struct in6_addr req_addr;
struct dhcp_context *dynamic, *c;
unsigned int lease_time;
- struct in6_addr addr;
int config_ok = 0;
/* align. */
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
- config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr);
+ config_ok = config_implies(config, c, &req_addr);
if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
{
@@ -1032,12 +1032,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
(this_context = address6_valid(state->context, &req_addr, tagif, 1)))
{
- struct in6_addr addr;
unsigned int lease_time;
get_context_tag(state, this_context);
- if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr) && have_config(config, CONFIG_TIME))
+ if (config_implies(config, this_context, &req_addr) && have_config(config, CONFIG_TIME))
lease_time = config->lease_time;
else
lease_time = this_context->lease_time;
@@ -1760,6 +1759,76 @@ static int check_address(struct state *state, struct in6_addr *addr)
}
+/* return true of *addr could have been generated from config. */
+static int config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
+{
+ int prefix;
+ struct in6_addr wild_addr;
+ struct addrlist *addr_list;
+
+ if (!config || !(config->flags & CONFIG_ADDR6))
+ return 0;
+
+ for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
+ {
+ prefix = (addr_list->flags & ADDRLIST_PREFIX) ? addr_list->prefixlen : 128;
+ wild_addr = addr_list->addr.addr.addr6;
+
+ if ((addr_list->flags & ADDRLIST_WILDCARD) && context->prefix == 64)
+ {
+ wild_addr = context->start6;
+ setaddr6part(&wild_addr, addr6part(&addr_list->addr.addr.addr6));
+ }
+ else if (!is_same_net6(&context->start6, addr, context->prefix))
+ continue;
+
+ if (is_same_net6(&wild_addr, addr, prefix))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state)
+{
+ u64 addrpart, i, addresses;
+ struct addrlist *addr_list;
+
+ if (!config || !(config->flags & CONFIG_ADDR6))
+ return 0;
+
+ for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
+ {
+ addrpart = addr6part(&addr_list->addr.addr.addr6);
+ addresses = 1;
+
+ if (addr_list->flags & ADDRLIST_PREFIX)
+ addresses = 1<<(128-addr_list->prefixlen);
+
+ if ((addr_list->flags & ADDRLIST_WILDCARD))
+ {
+ if (context->prefix != 64)
+ continue;
+
+ *addr = context->start6;
+ }
+ else if (is_same_net6(&context->start6, &addr_list->addr.addr.addr6, context->prefix))
+ *addr = addr_list->addr.addr.addr6;
+ else
+ continue;
+
+ for (i = 0 ; i < addresses; i++)
+ {
+ setaddr6part(addr, addrpart+i);
+
+ if (check_address(state, addr))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* Calculate valid and preferred times to send in leases/renewals.
Inputs are:
--
1.8.3.1

View File

@ -0,0 +1,62 @@
From 3d113137fd64cd0723cbecab6a36a75d3ecfb0a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Harald=20Jens=C3=A5s?= <hjensas@redhat.com>
Date: Thu, 7 May 2020 00:33:54 +0200
Subject: [PATCH 1/1] Fix regression in s_config_in_context() method
Prior to commit 137286e9baecf6a3ba97722ef1b49c851b531810
a config would not be considered in context if:
a) it has no address family flags set
b) it has the address family flag of current context set
Since above commit config is considered in context if the
address family is the opposite of current context.
The result is that a config with two dhcp-host records,
one for IPv6 and another for IPv4 no longer works, for
example with the below config the config with the IPv6
address would be considered in context for a DHCP(v4)
request.
dhcp-host=52:54:00:bc:c3:fd,172.20.0.11,host2
dhcp-host=52:54:00:bc:c3:fd,[fd12:3456:789a:1::aadd],host2
This commit restores the previous behavior.
---
src/dhcp-common.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index eae9886..ffc78ca 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -280,14 +280,18 @@ static int is_config_in_context(struct dhcp_context *context, struct dhcp_config
{
if (!context) /* called via find_config() from lease_update_from_configs() */
return 1;
-
+
+ /* No address present in config == in context */
+ if (!(config->flags & (CONFIG_ADDR | CONFIG_ADDR6)))
+ return 1;
+
#ifdef HAVE_DHCP6
if (context->flags & CONTEXT_V6)
{
struct addrlist *addr_list;
if (!(config->flags & CONFIG_ADDR6))
- return 1;
+ return 0;
for (; context; context = context->current)
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
@@ -303,7 +307,7 @@ static int is_config_in_context(struct dhcp_context *context, struct dhcp_config
#endif
{
if (!(config->flags & CONFIG_ADDR))
- return 1;
+ return 0;
for (; context; context = context->current)
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
--
2.25.4

View File

@ -0,0 +1,322 @@
From dd04a0d90d2fca66b5f91952ae7286c5de1714f1 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Fri, 7 Feb 2020 21:05:54 +0000
Subject: [PATCH] Add tag filtering of dhcp-host directives.
(cherry picked from commit 52ec7836139e7a11374971905e5ac0d2d02e32c0)
Conflicts:
CHANGELOG
src/rfc3315.c
---
man/dnsmasq.8 | 5 ++++-
src/dhcp-common.c | 42 ++++++++++++++++++++++++++++++++----------
src/dnsmasq.h | 4 +++-
src/lease.c | 2 +-
src/option.c | 14 ++++++--------
src/rfc2131.c | 6 +++---
src/rfc3315.c | 49 ++++++++++++++++++++++---------------------------
7 files changed, 71 insertions(+), 51 deletions(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 2c9d9f6..a59b06f 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -953,7 +953,7 @@ is also included, as described in RFC-3775 section 7.3.
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
.TP
-.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
+.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][tag:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
Specify per host parameters for the DHCP server. This allows a machine
with a particular hardware address to be always allocated the same
hostname, IP address and lease time. A hostname specified like this
@@ -1038,6 +1038,9 @@ ignore requests from unknown machines using
.B --dhcp-ignore=tag:!known
If the host matches only a dhcp-host directive which cannot
be used because it specifies an address on different subnet, the tag "known-othernet" is set.
+
+The tag:<tag> construct filters which dhcp-host directives are used. Tagged directives are used in preference to untagged ones.
+
Ethernet addresses (but not client-ids) may have
wildcard bytes, so for example
.B --dhcp-host=00:20:e0:3b:13:*,ignore
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index 5d437dd..71e9e5b 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -304,11 +304,12 @@ static int is_config_in_context(struct dhcp_context *context, struct dhcp_config
return 0;
}
-struct dhcp_config *find_config(struct dhcp_config *configs,
- struct dhcp_context *context,
- unsigned char *clid, int clid_len,
- unsigned char *hwaddr, int hw_len,
- int hw_type, char *hostname)
+static struct dhcp_config *find_config_match(struct dhcp_config *configs,
+ struct dhcp_context *context,
+ unsigned char *clid, int clid_len,
+ unsigned char *hwaddr, int hw_len,
+ int hw_type, char *hostname,
+ struct dhcp_netid *tags, int tag_not_needed)
{
int count, new;
struct dhcp_config *config, *candidate;
@@ -320,7 +321,9 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
{
if (config->clid_len == clid_len &&
memcmp(config->clid, clid, clid_len) == 0 &&
- is_config_in_context(context, config))
+ is_config_in_context(context, config) &&
+ match_netid(config->filter, tags, tag_not_needed))
+
return config;
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
@@ -328,7 +331,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
see lease_update_from_configs() */
if ((!context || !(context->flags & CONTEXT_V6)) && *clid == 0 && config->clid_len == clid_len-1 &&
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
- is_config_in_context(context, config))
+ is_config_in_context(context, config) &&
+ match_netid(config->filter, tags, tag_not_needed))
return config;
}
@@ -336,14 +340,16 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
if (hwaddr)
for (config = configs; config; config = config->next)
if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
- is_config_in_context(context, config))
+ is_config_in_context(context, config) &&
+ match_netid(config->filter, tags, tag_not_needed))
return config;
if (hostname && context)
for (config = configs; config; config = config->next)
if ((config->flags & CONFIG_NAME) &&
hostname_isequal(config->hostname, hostname) &&
- is_config_in_context(context, config))
+ is_config_in_context(context, config) &&
+ match_netid(config->filter, tags, tag_not_needed))
return config;
@@ -352,7 +358,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
/* use match with fewest wildcard octets */
for (candidate = NULL, count = 0, config = configs; config; config = config->next)
- if (is_config_in_context(context, config))
+ if (is_config_in_context(context, config) &&
+ match_netid(config->filter, tags, tag_not_needed))
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
if (conf_addr->wildcard_mask != 0 &&
conf_addr->hwaddr_len == hw_len &&
@@ -366,6 +373,21 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
return candidate;
}
+/* Find tagged configs first. */
+struct dhcp_config *find_config(struct dhcp_config *configs,
+ struct dhcp_context *context,
+ unsigned char *clid, int clid_len,
+ unsigned char *hwaddr, int hw_len,
+ int hw_type, char *hostname, struct dhcp_netid *tags)
+{
+ struct dhcp_config *ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 0);
+
+ if (!ret)
+ ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 1);
+
+ return ret;
+}
+
void dhcp_update_configs(struct dhcp_config *configs)
{
/* Some people like to keep all static IP addresses in /etc/hosts.
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 9437226..055a0d1 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -749,6 +749,7 @@ struct dhcp_config {
unsigned char *clid; /* clientid */
char *hostname, *domain;
struct dhcp_netid_list *netid;
+ struct dhcp_netid *filter;
#ifdef HAVE_DHCP6
struct addrlist *addr6;
#endif
@@ -1514,7 +1515,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
struct dhcp_context *context,
unsigned char *clid, int clid_len,
unsigned char *hwaddr, int hw_len,
- int hw_type, char *hostname);
+ int hw_type, char *hostname,
+ struct dhcp_netid *filter);
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
#ifdef HAVE_LINUX_NETWORK
char *whichdevice(void);
diff --git a/src/lease.c b/src/lease.c
index 5c33df7..00c82f6 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -222,7 +222,7 @@ void lease_update_from_configs(void)
if (lease->flags & (LEASE_TA | LEASE_NA))
continue;
else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
- lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
+ lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL, NULL)) &&
(config->flags & CONFIG_NAME) &&
(!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
diff --git a/src/option.c b/src/option.c
index ea70ee3..88cd2ab 100644
--- a/src/option.c
+++ b/src/option.c
@@ -953,8 +953,7 @@ static char *set_prefix(char *arg)
return arg;
}
-static struct dhcp_netid *
-dhcp_netid_create(const char *net, struct dhcp_netid *next)
+static struct dhcp_netid *dhcp_netid_create(const char *net, struct dhcp_netid *next)
{
struct dhcp_netid *tt;
tt = opt_malloc(sizeof (struct dhcp_netid));
@@ -1019,7 +1018,8 @@ static void dhcp_config_free(struct dhcp_config *config)
}
dhcp_netid_list_free(config->netid);
-
+ dhcp_netid_free(config->filter);
+
if (config->flags & CONFIG_CLID)
free(config->clid);
@@ -3167,6 +3167,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
new->hwaddr = NULL;
new->netid = NULL;
+ new->filter = NULL;
new->clid = NULL;
new->addr6 = NULL;
@@ -3215,11 +3216,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
newlist->list = dhcp_netid_create(arg+4, NULL);
}
else if (strstr(arg, "tag:") == arg)
- {
-
- dhcp_config_free(new);
- ret_err(_("cannot match tags in --dhcp-host"));
- }
+ new->filter = dhcp_netid_create(arg+4, new->filter);
+
#ifdef HAVE_DHCP6
else if (arg[0] == '[' && arg[strlen(arg)-1] == ']')
{
diff --git a/src/rfc2131.c b/src/rfc2131.c
index 997575a..a741f9f 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -479,7 +479,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
mess->op = BOOTREPLY;
config = find_config(daemon->dhcp_conf, context, clid, clid_len,
- mess->chaddr, mess->hlen, mess->htype, NULL);
+ mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid));
/* set "known" tag for known hosts */
if (config)
@@ -489,7 +489,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
netid = &known_id;
}
else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len,
- mess->chaddr, mess->hlen, mess->htype, NULL))
+ mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid)))
{
known_id.net = "known-othernet";
known_id.next = netid;
@@ -725,7 +725,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
to avoid impersonation by name. */
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
mess->chaddr, mess->hlen,
- mess->htype, hostname);
+ mess->htype, hostname, run_tag_if(netid));
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
{
config = new;
diff --git a/src/rfc3315.c b/src/rfc3315.c
index ee58b57..a0067e9 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -486,35 +486,29 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
}
}
- if (state->clid)
+ if (state->clid &&
+ (config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len,
+ state->mac, state->mac_len, state->mac_type, NULL, run_tag_if(state->tags))) &&
+ have_config(config, CONFIG_NAME))
{
- config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL);
-
- if (have_config(config, CONFIG_NAME))
- {
- state->hostname = config->hostname;
- state->domain = config->domain;
- state->hostname_auth = 1;
- }
- else if (state->client_hostname)
- {
- state->domain = strip_hostname(state->client_hostname);
+ state->hostname = config->hostname;
+ state->domain = config->domain;
+ state->hostname_auth = 1;
+ }
+ else if (state->client_hostname)
+ {
+ state->domain = strip_hostname(state->client_hostname);
- if (strlen(state->client_hostname) != 0)
- {
- state->hostname = state->client_hostname;
- if (!config)
- {
- /* Search again now we have a hostname.
- Only accept configs without CLID here, (it won't match)
- to avoid impersonation by name. */
- struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname);
- if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
- config = new;
- }
- }
+ if (strlen(state->client_hostname) != 0)
+ {
+ /* Search again now we have a hostname.
+ Only accept configs without CLID here, (it won't match)
+ to avoid impersonation by name. */
+ struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname, run_tag_if(state->tags));
+ if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
+ config = new;
}
- }
+ }
if (config)
{
@@ -535,7 +529,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
ignore = 1;
}
else if (state->clid &&
- find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL))
+ find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len,
+ state->mac, state->mac_len, state->mac_type, NULL, run_tag_if(state->tags)))
{
known_id.net = "known-othernet";
known_id.next = state->tags;
--
1.8.3.1

View File

@ -13,7 +13,7 @@
Name: dnsmasq
Version: 2.79
Release: 9%{?extraversion:.%{extraversion}}%{?dist}
Release: 13%{?extraversion:.%{extraversion}}%{?dist}
Summary: A lightweight DHCP/caching DNS server
License: GPLv2 or GPLv3
@ -39,6 +39,19 @@ Patch11: dnsmasq-2.76-rh1728698-3.patch
Patch12: dnsmasq-2.79-rh1728698-4.patch
Patch13: dnsmasq-2.79-rh1746411.patch
Patch14: dnsmasq-2.79-rh1700916.patch
Patch15: dnsmasq-2.80-rh1795370.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1779187
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=97f876b64c22b2b18412e2e3d8506ee33e42db7c
Patch16: dnsmasq-2.80-unaligned-addresses-in-DHCPv6-packet.patch
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=f064188032a829efdcf3988b24ac795ff52785ec
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=137286e9baecf6a3ba97722ef1b49c851b531810
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=79aba0f10ad0157fb4f48afbbcb03f094caff97a
Patch17: dnsmasq-2.81-prefix-ranges-or-list-of-ipv6-addresses.patch
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=52ec7836139e7a11374971905e5ac0d2d02e32c0
Patch18: dnsmasq-2.81-tag-filtering-of-dhcp-host-directives.patch
Patch19: dnsmasq-2.81-correct-range-check-of-dhcp-host-prefix.patch
Patch20: dnsmasq-2.81-optimize-fds-close.patch
Patch21: dnsmasq-2.81-rh1829448.patch
# This is workaround to nettle bug #1549190
# https://bugzilla.redhat.com/show_bug.cgi?id=1549190
@ -86,6 +99,13 @@ server's leases.
%patch12 -p1 -b .rh1728698-4
%patch13 -p1 -b .rh1746411
%patch14 -p1 -b .rh1700916
%patch15 -p1 -b .rh1795370
%patch16 -p1 -b .rh1779187-1
%patch17 -p1 -b .rh1779187-2
%patch18 -p1 -b .rh1779187-3
%patch19 -p1 -b .rh1779187-4
%patch20 -p1 -b .rh1816613
%patch21 -p1 -b .rh1829448
# use /var/lib/dnsmasq instead of /var/lib/misc
for file in dnsmasq.conf.example man/dnsmasq.8 man/es/dnsmasq.8 src/config.h; do
@ -186,6 +206,18 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/dnsmasq.conf
%{_mandir}/man1/dhcp_*
%changelog
* Tue May 05 2020 Petr Menšík <pemensik@redhat.com> - 2.79-13
- Fix mixed address family reservations on DHCP (#1829448)
* Mon Mar 30 2020 Tomas Korbar <tkorbar@redhat.com> - 2.79-12
- Minimize count of close syscalls on startup (#1816613)
* Mon Mar 02 2020 Petr Menšík <pemensik@redhat.com> - 2.79-11
- Support multiple static leases for single mac on IPv6 (#1779187)
* Mon Feb 17 2020 Tomas Korbar <tkorbar@redhat.com> - 2.79-10
- Fix memory leak in helper.c (#1795370)
* Tue Dec 10 2019 Tomas Korbar <tkorbar@redhat.com> - 2.79-9
- Fix replies to non-recursive queries (#1700916)