Compare commits
14 Commits
imports/c8
...
c8
Author | SHA1 | Date | |
---|---|---|---|
4627e162a6 | |||
|
9f1ac11479 | ||
|
839fc82576 | ||
|
70671aa970 | ||
|
7d2efecdd7 | ||
|
b20b5e21a7 | ||
|
1332433a88 | ||
|
1da786ce0d | ||
|
4b30fdd332 | ||
|
54b39b34c6 | ||
|
65bd378a1d | ||
|
6f3f42358a | ||
|
7b92db154a | ||
|
b329adf800 |
364
SOURCES/dnsmasq-2.79-CVE-2020-25681.patch
Normal file
364
SOURCES/dnsmasq-2.79-CVE-2020-25681.patch
Normal file
@ -0,0 +1,364 @@
|
||||
From 6689e336042d2ca0b075f8db1fe30ed6b47c7d4c Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Wed, 11 Nov 2020 23:25:04 +0000
|
||||
Subject: [PATCH 1/4] Fix remote buffer overflow CERT VU#434904
|
||||
|
||||
The problem is in the sort_rrset() function and allows a remote
|
||||
attacker to overwrite memory. Any dnsmasq instance with DNSSEC
|
||||
enabled is vulnerable.
|
||||
---
|
||||
src/dnssec.c | 273 ++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 152 insertions(+), 121 deletions(-)
|
||||
|
||||
diff --git a/src/dnssec.c b/src/dnssec.c
|
||||
index 8143185..0c703ac 100644
|
||||
--- a/src/dnssec.c
|
||||
+++ b/src/dnssec.c
|
||||
@@ -222,138 +222,147 @@ static int check_date_range(u32 date_start, u32 date_end)
|
||||
&& serial_compare_32(curtime, date_end) == SERIAL_LT;
|
||||
}
|
||||
|
||||
-/* Return bytes of canonicalised rdata, when the return value is zero, the remaining
|
||||
- data, pointed to by *p, should be used raw. */
|
||||
-static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen,
|
||||
- unsigned char **p, u16 **desc)
|
||||
+/* Return bytes of canonicalised rrdata one by one.
|
||||
+ Init state->ip with the RR, and state->end with the end of same.
|
||||
+ Init state->op to NULL.
|
||||
+ Init state->desc to RR descriptor.
|
||||
+ Init state->buff with a MAXDNAME * 2 buffer.
|
||||
+
|
||||
+ After each call which returns 1, state->op points to the next byte of data.
|
||||
+ On returning 0, the end has been reached.
|
||||
+*/
|
||||
+struct rdata_state {
|
||||
+ u16 *desc;
|
||||
+ size_t c;
|
||||
+ unsigned char *end, *ip, *op;
|
||||
+ char *buff;
|
||||
+};
|
||||
+
|
||||
+static int get_rdata(struct dns_header *header, size_t plen, struct rdata_state *state)
|
||||
{
|
||||
- int d = **desc;
|
||||
+ int d;
|
||||
|
||||
- /* No more data needs mangling */
|
||||
- if (d == (u16)-1)
|
||||
+ if (state->op && state->c != 1)
|
||||
{
|
||||
- /* If there's more data than we have space for, just return what fits,
|
||||
- we'll get called again for more chunks */
|
||||
- if (end - *p > bufflen)
|
||||
- {
|
||||
- memcpy(buff, *p, bufflen);
|
||||
- *p += bufflen;
|
||||
- return bufflen;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
+ state->op++;
|
||||
+ state->c--;
|
||||
+ return 1;
|
||||
}
|
||||
-
|
||||
- (*desc)++;
|
||||
-
|
||||
- if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
|
||||
- /* domain-name, canonicalise */
|
||||
- return to_wire(buff);
|
||||
- else
|
||||
- {
|
||||
- /* plain data preceding a domain-name, don't run off the end of the data */
|
||||
- if ((end - *p) < d)
|
||||
- d = end - *p;
|
||||
+
|
||||
+ while (1)
|
||||
+ {
|
||||
+ d = *(state->desc);
|
||||
|
||||
- if (d != 0)
|
||||
+ if (d == (u16)-1)
|
||||
{
|
||||
- memcpy(buff, *p, d);
|
||||
- *p += d;
|
||||
+ /* all the bytes to the end. */
|
||||
+ if ((state->c = state->end - state->ip) != 0)
|
||||
+ {
|
||||
+ state->op = state->ip;
|
||||
+ state->ip = state->end;;
|
||||
+ }
|
||||
+ else
|
||||
+ return 0;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ state->desc++;
|
||||
+
|
||||
+ if (d == (u16)0)
|
||||
+ {
|
||||
+ /* domain-name, canonicalise */
|
||||
+ int len;
|
||||
+
|
||||
+ if (!extract_name(header, plen, &state->ip, state->buff, 1, 0) ||
|
||||
+ (len = to_wire(state->buff)) == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ state->c = len;
|
||||
+ state->op = (unsigned char *)state->buff;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* plain data preceding a domain-name, don't run off the end of the data */
|
||||
+ if ((state->end - state->ip) < d)
|
||||
+ d = state->end - state->ip;
|
||||
+
|
||||
+ if (d == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ state->op = state->ip;
|
||||
+ state->c = d;
|
||||
+ state->ip += d;
|
||||
+ }
|
||||
}
|
||||
|
||||
- return d;
|
||||
+ return 1;
|
||||
}
|
||||
}
|
||||
|
||||
-/* Bubble sort the RRset into the canonical order.
|
||||
- Note that the byte-streams from two RRs may get unsynced: consider
|
||||
- RRs which have two domain-names at the start and then other data.
|
||||
- The domain-names may have different lengths in each RR, but sort equal
|
||||
-
|
||||
- ------------
|
||||
- |abcde|fghi|
|
||||
- ------------
|
||||
- |abcd|efghi|
|
||||
- ------------
|
||||
-
|
||||
- leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
|
||||
-*/
|
||||
+/* Bubble sort the RRset into the canonical order. */
|
||||
|
||||
static int sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
|
||||
unsigned char **rrset, char *buff1, char *buff2)
|
||||
{
|
||||
- int swap, quit, i, j;
|
||||
+ int swap, i, j;
|
||||
|
||||
do
|
||||
{
|
||||
for (swap = 0, i = 0; i < rrsetidx-1; i++)
|
||||
{
|
||||
- int rdlen1, rdlen2, left1, left2, len1, len2, len, rc;
|
||||
- u16 *dp1, *dp2;
|
||||
- unsigned char *end1, *end2;
|
||||
+ int rdlen1, rdlen2;
|
||||
+ struct rdata_state state1, state2;
|
||||
+
|
||||
/* Note that these have been determined to be OK previously,
|
||||
so we don't need to check for NULL return here. */
|
||||
- unsigned char *p1 = skip_name(rrset[i], header, plen, 10);
|
||||
- unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10);
|
||||
-
|
||||
- p1 += 8; /* skip class, type, ttl */
|
||||
- GETSHORT(rdlen1, p1);
|
||||
- end1 = p1 + rdlen1;
|
||||
-
|
||||
- p2 += 8; /* skip class, type, ttl */
|
||||
- GETSHORT(rdlen2, p2);
|
||||
- end2 = p2 + rdlen2;
|
||||
+ state1.ip = skip_name(rrset[i], header, plen, 10);
|
||||
+ state2.ip = skip_name(rrset[i+1], header, plen, 10);
|
||||
+ state1.op = state2.op = NULL;
|
||||
+ state1.buff = buff1;
|
||||
+ state2.buff = buff2;
|
||||
+ state1.desc = state2.desc = rr_desc;
|
||||
|
||||
- dp1 = dp2 = rr_desc;
|
||||
+ state1.ip += 8; /* skip class, type, ttl */
|
||||
+ GETSHORT(rdlen1, state1.ip);
|
||||
+ if (!CHECK_LEN(header, state1.ip, plen, rdlen1))
|
||||
+ return rrsetidx; /* short packet */
|
||||
+ state1.end = state1.ip + rdlen1;
|
||||
|
||||
- for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
|
||||
+ state2.ip += 8; /* skip class, type, ttl */
|
||||
+ GETSHORT(rdlen2, state2.ip);
|
||||
+ if (!CHECK_LEN(header, state2.ip, plen, rdlen2))
|
||||
+ return rrsetidx; /* short packet */
|
||||
+ state2.end = state2.ip + rdlen2;
|
||||
+
|
||||
+ while (1)
|
||||
{
|
||||
- if (left1 != 0)
|
||||
- memmove(buff1, buff1 + len1 - left1, left1);
|
||||
+ int ok1, ok2;
|
||||
|
||||
- if ((len1 = get_rdata(header, plen, end1, buff1 + left1, (MAXDNAME * 2) - left1, &p1, &dp1)) == 0)
|
||||
- {
|
||||
- quit = 1;
|
||||
- len1 = end1 - p1;
|
||||
- memcpy(buff1 + left1, p1, len1);
|
||||
- }
|
||||
- len1 += left1;
|
||||
-
|
||||
- if (left2 != 0)
|
||||
- memmove(buff2, buff2 + len2 - left2, left2);
|
||||
-
|
||||
- if ((len2 = get_rdata(header, plen, end2, buff2 + left2, (MAXDNAME *2) - left2, &p2, &dp2)) == 0)
|
||||
- {
|
||||
- quit = 1;
|
||||
- len2 = end2 - p2;
|
||||
- memcpy(buff2 + left2, p2, len2);
|
||||
- }
|
||||
- len2 += left2;
|
||||
-
|
||||
- if (len1 > len2)
|
||||
- left1 = len1 - len2, left2 = 0, len = len2;
|
||||
- else
|
||||
- left2 = len2 - len1, left1 = 0, len = len1;
|
||||
-
|
||||
- rc = (len == 0) ? 0 : memcmp(buff1, buff2, len);
|
||||
-
|
||||
- if (rc > 0 || (rc == 0 && quit && len1 > len2))
|
||||
- {
|
||||
- unsigned char *tmp = rrset[i+1];
|
||||
- rrset[i+1] = rrset[i];
|
||||
- rrset[i] = tmp;
|
||||
- swap = quit = 1;
|
||||
- }
|
||||
- else if (rc == 0 && quit && len1 == len2)
|
||||
+ ok1 = get_rdata(header, plen, &state1);
|
||||
+ ok2 = get_rdata(header, plen, &state2);
|
||||
+
|
||||
+ if (!ok1 && !ok2)
|
||||
{
|
||||
/* Two RRs are equal, remove one copy. RFC 4034, para 6.3 */
|
||||
for (j = i+1; j < rrsetidx-1; j++)
|
||||
rrset[j] = rrset[j+1];
|
||||
rrsetidx--;
|
||||
i--;
|
||||
+ break;
|
||||
+ }
|
||||
+ else if (ok1 && (!ok2 || *state1.op > *state2.op))
|
||||
+ {
|
||||
+ unsigned char *tmp = rrset[i+1];
|
||||
+ rrset[i+1] = rrset[i];
|
||||
+ rrset[i] = tmp;
|
||||
+ swap = 1;
|
||||
+ break;
|
||||
}
|
||||
- else if (rc < 0)
|
||||
- quit = 1;
|
||||
+ else if (ok2 && (!ok1 || *state2.op > *state1.op))
|
||||
+ break;
|
||||
+
|
||||
+ /* arrive here when bytes are equal, go round the loop again
|
||||
+ and compare the next ones. */
|
||||
}
|
||||
}
|
||||
} while (swap);
|
||||
@@ -549,15 +558,18 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
||||
wire_len = to_wire(keyname);
|
||||
hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
|
||||
from_wire(keyname);
|
||||
+
|
||||
+#define RRBUFLEN 300 /* Most RRs are smaller than this. */
|
||||
|
||||
for (i = 0; i < rrsetidx; ++i)
|
||||
{
|
||||
- int seg;
|
||||
- unsigned char *end, *cp;
|
||||
- u16 len, *dp;
|
||||
+ int j;
|
||||
+ struct rdata_state state;
|
||||
+ u16 len;
|
||||
+ unsigned char rrbuf[RRBUFLEN];
|
||||
|
||||
p = rrset[i];
|
||||
-
|
||||
+
|
||||
if (!extract_name(header, plen, &p, name, 1, 10))
|
||||
return STAT_BOGUS;
|
||||
|
||||
@@ -566,12 +578,11 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
||||
/* if more labels than in RRsig name, hash *.<no labels in rrsig labels field> 4035 5.3.2 */
|
||||
if (labels < name_labels)
|
||||
{
|
||||
- int k;
|
||||
- for (k = name_labels - labels; k != 0; k--)
|
||||
+ for (j = name_labels - labels; j != 0; j--)
|
||||
{
|
||||
while (*name_start != '.' && *name_start != 0)
|
||||
name_start++;
|
||||
- if (k != 1 && *name_start == '.')
|
||||
+ if (j != 1 && *name_start == '.')
|
||||
name_start++;
|
||||
}
|
||||
|
||||
@@ -592,24 +603,44 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
||||
if (!CHECK_LEN(header, p, plen, rdlen))
|
||||
return STAT_BOGUS;
|
||||
|
||||
- end = p + rdlen;
|
||||
+ /* canonicalise rdata and calculate length of same, use
|
||||
+ name buffer as workspace for get_rdata. */
|
||||
+ state.ip = p;
|
||||
+ state.op = NULL;
|
||||
+ state.desc = rr_desc;
|
||||
+ state.buff = name;
|
||||
+ state.end = p + rdlen;
|
||||
|
||||
- /* canonicalise rdata and calculate length of same, use name buffer as workspace.
|
||||
- Note that name buffer is twice MAXDNAME long in DNSSEC mode. */
|
||||
- cp = p;
|
||||
- dp = rr_desc;
|
||||
- for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)) != 0; len += seg);
|
||||
- len += end - cp;
|
||||
- len = htons(len);
|
||||
+ for (j = 0; get_rdata(header, plen, &state); j++)
|
||||
+ if (j < RRBUFLEN)
|
||||
+ rrbuf[j] = *state.op;
|
||||
+
|
||||
+ len = htons((u16)j);
|
||||
hash->update(ctx, 2, (unsigned char *)&len);
|
||||
+
|
||||
+ /* If the RR is shorter than RRBUFLEN (most of them, in practice)
|
||||
+ then we can just digest it now. If it exceeds RRBUFLEN we have to
|
||||
+ go back to the start and do it in chunks. */
|
||||
+ if (j >= RRBUFLEN)
|
||||
+ {
|
||||
+ state.ip = p;
|
||||
+ state.op = NULL;
|
||||
+ state.desc = rr_desc;
|
||||
+
|
||||
+ for (j = 0; get_rdata(header, plen, &state); j++)
|
||||
+ {
|
||||
+ rrbuf[j] = *state.op;
|
||||
+
|
||||
+ if (j == RRBUFLEN - 1)
|
||||
+ {
|
||||
+ hash->update(ctx, RRBUFLEN, rrbuf);
|
||||
+ j = -1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- /* Now canonicalise again and digest. */
|
||||
- cp = p;
|
||||
- dp = rr_desc;
|
||||
- while ((seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)))
|
||||
- hash->update(ctx, seg, (unsigned char *)name);
|
||||
- if (cp != end)
|
||||
- hash->update(ctx, end - cp, cp);
|
||||
+ if (j != 0)
|
||||
+ hash->update(ctx, j, rrbuf);
|
||||
}
|
||||
|
||||
hash->digest(ctx, hash->digest_size, digest);
|
||||
--
|
||||
2.26.2
|
||||
|
94
SOURCES/dnsmasq-2.79-CVE-2020-25684.patch
Normal file
94
SOURCES/dnsmasq-2.79-CVE-2020-25684.patch
Normal file
@ -0,0 +1,94 @@
|
||||
From 04ef96f428beebd07b457b51b5d2f26d3099f1a5 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Thu, 12 Nov 2020 18:49:23 +0000
|
||||
Subject: [PATCH 2/4] Check destination of DNS UDP query replies.
|
||||
|
||||
At any time, dnsmasq will have a set of sockets open, bound to
|
||||
random ports, on which it sends queries to upstream nameservers.
|
||||
This patch fixes the existing problem that a reply for ANY in-flight
|
||||
query would be accepted via ANY open port, which increases the
|
||||
chances of an attacker flooding answers "in the blind" in an
|
||||
attempt to poison the DNS cache. CERT VU#434904 refers.
|
||||
---
|
||||
src/forward.c | 37 ++++++++++++++++++++++++++++---------
|
||||
1 file changed, 28 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index cdd11d3..85eab27 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
-static struct frec *lookup_frec(unsigned short id, void *hash);
|
||||
+static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash);
|
||||
static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||
union mysockaddr *addr,
|
||||
void *hash);
|
||||
@@ -780,7 +780,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
crc = questions_crc(header, n, daemon->namebuff);
|
||||
#endif
|
||||
|
||||
- if (!(forward = lookup_frec(ntohs(header->id), hash)))
|
||||
+ if (!(forward = lookup_frec(ntohs(header->id), fd, family, hash)))
|
||||
return;
|
||||
|
||||
/* log_query gets called indirectly all over the place, so
|
||||
@@ -2195,14 +2195,25 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
|
||||
}
|
||||
|
||||
/* crc is all-ones if not known. */
|
||||
-static struct frec *lookup_frec(unsigned short id, void *hash)
|
||||
+static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash)
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
for(f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto && f->new_id == id &&
|
||||
(!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
|
||||
- return f;
|
||||
+ {
|
||||
+ /* sent from random port */
|
||||
+ if (family == AF_INET && f->rfd4 && f->rfd4->fd == fd)
|
||||
+ return f;
|
||||
+
|
||||
+ if (family == AF_INET6 && f->rfd6 && f->rfd6->fd == fd)
|
||||
+ return f;
|
||||
+
|
||||
+ /* sent to upstream from bound socket. */
|
||||
+ if (f->sentto->sfd && f->sentto->sfd->fd == fd)
|
||||
+ return f;
|
||||
+ }
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -2263,12 +2274,20 @@ void server_gone(struct server *server)
|
||||
static unsigned short get_id(void)
|
||||
{
|
||||
unsigned short ret = 0;
|
||||
+ struct frec *f;
|
||||
|
||||
- do
|
||||
- ret = rand16();
|
||||
- while (lookup_frec(ret, NULL));
|
||||
-
|
||||
- return ret;
|
||||
+ while (1)
|
||||
+ {
|
||||
+ ret = rand16();
|
||||
+
|
||||
+ /* ensure id is unique. */
|
||||
+ for (f = daemon->frec_list; f; f = f->next)
|
||||
+ if (f->sentto && f->new_id == ret)
|
||||
+ break;
|
||||
+
|
||||
+ if (!f)
|
||||
+ return ret;
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
586
SOURCES/dnsmasq-2.79-CVE-2020-25685.patch
Normal file
586
SOURCES/dnsmasq-2.79-CVE-2020-25685.patch
Normal file
@ -0,0 +1,586 @@
|
||||
From 6cbbae54c9232f182cc76f05962a07244d748b75 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Thu, 12 Nov 2020 22:06:07 +0000
|
||||
Subject: [PATCH 3/4] Use SHA-256 to provide security against DNS cache
|
||||
poisoning.
|
||||
|
||||
Use the SHA-256 hash function to verify that DNS answers
|
||||
received are for the questions originally asked. This replaces
|
||||
the slightly insecure SHA-1 (when compiled with DNSSEC) or
|
||||
the very insecure CRC32 (otherwise). Refer: CERT VU#434904.
|
||||
---
|
||||
Makefile | 3 +-
|
||||
bld/Android.mk | 3 +-
|
||||
src/dnsmasq.h | 11 +-
|
||||
src/dnssec.c | 31 -----
|
||||
src/forward.c | 43 ++-----
|
||||
src/hash_questions.c | 281 +++++++++++++++++++++++++++++++++++++++++++
|
||||
src/rfc1035.c | 49 --------
|
||||
7 files changed, 297 insertions(+), 124 deletions(-)
|
||||
create mode 100644 src/hash_questions.c
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 98ec760..cbbe5d7 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -76,7 +76,8 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
||||
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
||||
- poll.o rrfilter.o edns0.o arp.o crypto.o
|
||||
+ poll.o rrfilter.o edns0.o arp.o crypto.o \
|
||||
+ hash_questions.o
|
||||
|
||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||
dns-protocol.h radv-protocol.h ip6addr.h
|
||||
diff --git a/bld/Android.mk b/bld/Android.mk
|
||||
index 80ec842..2db29c1 100644
|
||||
--- a/bld/Android.mk
|
||||
+++ b/bld/Android.mk
|
||||
@@ -10,7 +10,8 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||
radv.c slaac.c auth.c ipset.c domain.c \
|
||||
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
||||
- loop.c inotify.c poll.c rrfilter.c edns0.c arp.c crypto.c
|
||||
+ loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
|
||||
+ crypto.c hash_questions.c
|
||||
|
||||
LOCAL_MODULE := dnsmasq
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index 6773b69..f31503d 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -615,11 +615,7 @@ struct hostsfile {
|
||||
#define FREC_TEST_PKTSZ 256
|
||||
#define FREC_HAS_EXTRADATA 512
|
||||
|
||||
-#ifdef HAVE_DNSSEC
|
||||
-#define HASH_SIZE 20 /* SHA-1 digest size */
|
||||
-#else
|
||||
-#define HASH_SIZE sizeof(int)
|
||||
-#endif
|
||||
+#define HASH_SIZE 32 /* SHA-256 digest size */
|
||||
|
||||
struct frec {
|
||||
union mysockaddr source;
|
||||
@@ -1156,7 +1152,6 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
||||
struct bogus_addr *baddr, time_t now);
|
||||
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
||||
int check_for_local_domain(char *name, time_t now);
|
||||
-unsigned int questions_crc(struct dns_header *header, size_t plen, char *name);
|
||||
size_t resize_packet(struct dns_header *header, size_t plen,
|
||||
unsigned char *pheader, size_t hlen);
|
||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||
@@ -1184,9 +1179,11 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
int check_unsigned, int *neganswer, int *nons);
|
||||
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
||||
size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
||||
-unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
||||
int setup_timestamp(void);
|
||||
|
||||
+/* hash_questions.c */
|
||||
+unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name);
|
||||
+
|
||||
/* crypto.c */
|
||||
const struct nettle_hash *hash_find(char *name);
|
||||
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp);
|
||||
diff --git a/src/dnssec.c b/src/dnssec.c
|
||||
index 0c703ac..b2dda1b 100644
|
||||
--- a/src/dnssec.c
|
||||
+++ b/src/dnssec.c
|
||||
@@ -2095,35 +2095,4 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char
|
||||
return ret;
|
||||
}
|
||||
|
||||
-unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
|
||||
-{
|
||||
- int q;
|
||||
- unsigned int len;
|
||||
- unsigned char *p = (unsigned char *)(header+1);
|
||||
- const struct nettle_hash *hash;
|
||||
- void *ctx;
|
||||
- unsigned char *digest;
|
||||
-
|
||||
- if (!(hash = hash_find("sha1")) || !hash_init(hash, &ctx, &digest))
|
||||
- return NULL;
|
||||
-
|
||||
- for (q = ntohs(header->qdcount); q != 0; q--)
|
||||
- {
|
||||
- if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
- break; /* bad packet */
|
||||
-
|
||||
- len = to_wire(name);
|
||||
- hash->update(ctx, len, (unsigned char *)name);
|
||||
- /* CRC the class and type as well */
|
||||
- hash->update(ctx, 4, p);
|
||||
-
|
||||
- p += 4;
|
||||
- if (!CHECK_LEN(header, p, plen, 0))
|
||||
- break; /* bad packet */
|
||||
- }
|
||||
-
|
||||
- hash->digest(ctx, hash->digest_size, digest);
|
||||
- return digest;
|
||||
-}
|
||||
-
|
||||
#endif /* HAVE_DNSSEC */
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index 85eab27..7ffcaf7 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -239,19 +239,16 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
struct all_addr *addrp = NULL;
|
||||
unsigned int flags = 0;
|
||||
struct server *start = NULL;
|
||||
-#ifdef HAVE_DNSSEC
|
||||
void *hash = hash_questions(header, plen, daemon->namebuff);
|
||||
+#ifdef HAVE_DNSSEC
|
||||
int do_dnssec = 0;
|
||||
-#else
|
||||
- unsigned int crc = questions_crc(header, plen, daemon->namebuff);
|
||||
- void *hash = &crc;
|
||||
#endif
|
||||
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
|
||||
(void)do_bit;
|
||||
|
||||
/* may be no servers available. */
|
||||
- if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
|
||||
+ if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash)))
|
||||
{
|
||||
/* If we didn't get an answer advertising a maximal packet in EDNS,
|
||||
fall back to 1280, which should work everywhere on IPv6.
|
||||
@@ -741,9 +738,6 @@ void reply_query(int fd, int family, time_t now)
|
||||
size_t nn;
|
||||
struct server *server;
|
||||
void *hash;
|
||||
-#ifndef HAVE_DNSSEC
|
||||
- unsigned int crc;
|
||||
-#endif
|
||||
|
||||
/* packet buffer overwritten */
|
||||
daemon->srv_save = NULL;
|
||||
@@ -773,12 +767,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
|
||||
server->edns_pktsz = daemon->edns_pktsz;
|
||||
|
||||
-#ifdef HAVE_DNSSEC
|
||||
hash = hash_questions(header, n, daemon->namebuff);
|
||||
-#else
|
||||
- hash = &crc;
|
||||
- crc = questions_crc(header, n, daemon->namebuff);
|
||||
-#endif
|
||||
|
||||
if (!(forward = lookup_frec(ntohs(header->id), fd, family, hash)))
|
||||
return;
|
||||
@@ -1006,8 +995,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
|
||||
daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
|
||||
}
|
||||
- if ((hash = hash_questions(header, nn, daemon->namebuff)))
|
||||
- memcpy(new->hash, hash, HASH_SIZE);
|
||||
+ memcpy(new->hash, hash_questions(header, nn, daemon->namebuff), HASH_SIZE);
|
||||
new->new_id = get_id();
|
||||
header->id = htons(new->new_id);
|
||||
/* Save query for retransmission */
|
||||
@@ -1840,15 +1828,9 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
if (!flags && last_server)
|
||||
{
|
||||
struct server *firstsendto = NULL;
|
||||
-#ifdef HAVE_DNSSEC
|
||||
- unsigned char *newhash, hash[HASH_SIZE];
|
||||
- if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
|
||||
- memcpy(hash, newhash, HASH_SIZE);
|
||||
- else
|
||||
- memset(hash, 0, HASH_SIZE);
|
||||
-#else
|
||||
- unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
|
||||
-#endif
|
||||
+ unsigned char hash[HASH_SIZE];
|
||||
+ memcpy(hash, hash_questions(header, (unsigned int)size, daemon->namebuff), HASH_SIZE);
|
||||
+
|
||||
/* Loop round available servers until we succeed in connecting to one.
|
||||
Note that this code subtly ensures that consecutive queries on this connection
|
||||
which can go to the same server, do so. */
|
||||
@@ -1973,20 +1955,11 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
/* If the crc of the question section doesn't match the crc we sent, then
|
||||
someone might be attempting to insert bogus values into the cache by
|
||||
sending replies containing questions and bogus answers. */
|
||||
-#ifdef HAVE_DNSSEC
|
||||
- newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
|
||||
- if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
|
||||
+ if (memcmp(hash, hash_questions(header, (unsigned int)m, daemon->namebuff), HASH_SIZE) != 0)
|
||||
{
|
||||
m = 0;
|
||||
break;
|
||||
}
|
||||
-#else
|
||||
- if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
|
||||
- {
|
||||
- m = 0;
|
||||
- break;
|
||||
- }
|
||||
-#endif
|
||||
|
||||
m = process_reply(header, now, last_server, (unsigned int)m,
|
||||
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
|
||||
@@ -2201,7 +2174,7 @@ static struct frec *lookup_frec(unsigned short id, int fd, int family, void *has
|
||||
|
||||
for(f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto && f->new_id == id &&
|
||||
- (!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
|
||||
+ (memcmp(hash, f->hash, HASH_SIZE) == 0))
|
||||
{
|
||||
/* sent from random port */
|
||||
if (family == AF_INET && f->rfd4 && f->rfd4->fd == fd)
|
||||
diff --git a/src/hash_questions.c b/src/hash_questions.c
|
||||
new file mode 100644
|
||||
index 0000000..ae112ac
|
||||
--- /dev/null
|
||||
+++ b/src/hash_questions.c
|
||||
@@ -0,0 +1,281 @@
|
||||
+/* Copyright (c) 2012-2020 Simon Kelley
|
||||
+
|
||||
+ This program is free software; you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation; version 2 dated June, 1991, or
|
||||
+ (at your option) version 3 dated 29 June, 2007.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+
|
||||
+/* Hash the question section. This is used to safely detect query
|
||||
+ retransmission and to detect answers to questions we didn't ask, which
|
||||
+ might be poisoning attacks. Note that we decode the name rather
|
||||
+ than CRC the raw bytes, since replies might be compressed differently.
|
||||
+ We ignore case in the names for the same reason.
|
||||
+
|
||||
+ The hash used is SHA-256. If we're building with DNSSEC support,
|
||||
+ we use the Nettle cypto library. If not, we prefer not to
|
||||
+ add a dependency on Nettle, and use a stand-alone implementaion.
|
||||
+*/
|
||||
+
|
||||
+#include "dnsmasq.h"
|
||||
+
|
||||
+#ifdef HAVE_DNSSEC
|
||||
+unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name)
|
||||
+{
|
||||
+ int q;
|
||||
+ unsigned char *p = (unsigned char *)(header+1);
|
||||
+ const struct nettle_hash *hash;
|
||||
+ void *ctx;
|
||||
+ unsigned char *digest;
|
||||
+
|
||||
+ if (!(hash = hash_find("sha256")) || !hash_init(hash, &ctx, &digest))
|
||||
+ {
|
||||
+ /* don't think this can ever happen. */
|
||||
+ static unsigned char dummy[HASH_SIZE];
|
||||
+ static int warned = 0;
|
||||
+
|
||||
+ if (warned)
|
||||
+ my_syslog(LOG_ERR, _("Failed to create SHA-256 hash object"));
|
||||
+ warned = 1;
|
||||
+
|
||||
+ return dummy;
|
||||
+ }
|
||||
+
|
||||
+ for (q = ntohs(header->qdcount); q != 0; q--)
|
||||
+ {
|
||||
+ char *cp, c;
|
||||
+
|
||||
+ if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
+ break; /* bad packet */
|
||||
+
|
||||
+ for (cp = name; (c = *cp); cp++)
|
||||
+ if (c >= 'A' && c <= 'Z')
|
||||
+ *cp += 'a' - 'A';
|
||||
+
|
||||
+ hash->update(ctx, cp - name, (unsigned char *)name);
|
||||
+ /* CRC the class and type as well */
|
||||
+ hash->update(ctx, 4, p);
|
||||
+
|
||||
+ p += 4;
|
||||
+ if (!CHECK_LEN(header, p, plen, 0))
|
||||
+ break; /* bad packet */
|
||||
+ }
|
||||
+
|
||||
+ hash->digest(ctx, hash->digest_size, digest);
|
||||
+ return digest;
|
||||
+}
|
||||
+
|
||||
+#else /* HAVE_DNSSEC */
|
||||
+
|
||||
+#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
||||
+typedef unsigned char BYTE; // 8-bit byte
|
||||
+typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||
+
|
||||
+typedef struct {
|
||||
+ BYTE data[64];
|
||||
+ WORD datalen;
|
||||
+ unsigned long long bitlen;
|
||||
+ WORD state[8];
|
||||
+} SHA256_CTX;
|
||||
+
|
||||
+static void sha256_init(SHA256_CTX *ctx);
|
||||
+static void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
|
||||
+static void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
|
||||
+
|
||||
+
|
||||
+unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name)
|
||||
+{
|
||||
+ int q;
|
||||
+ unsigned char *p = (unsigned char *)(header+1);
|
||||
+ SHA256_CTX ctx;
|
||||
+ static BYTE digest[SHA256_BLOCK_SIZE];
|
||||
+
|
||||
+ sha256_init(&ctx);
|
||||
+
|
||||
+ for (q = ntohs(header->qdcount); q != 0; q--)
|
||||
+ {
|
||||
+ char *cp, c;
|
||||
+
|
||||
+ if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
+ break; /* bad packet */
|
||||
+
|
||||
+ for (cp = name; (c = *cp); cp++)
|
||||
+ if (c >= 'A' && c <= 'Z')
|
||||
+ *cp += 'a' - 'A';
|
||||
+
|
||||
+ sha256_update(&ctx, (BYTE *)name, cp - name);
|
||||
+ /* CRC the class and type as well */
|
||||
+ sha256_update(&ctx, (BYTE *)p, 4);
|
||||
+
|
||||
+ p += 4;
|
||||
+ if (!CHECK_LEN(header, p, plen, 0))
|
||||
+ break; /* bad packet */
|
||||
+ }
|
||||
+
|
||||
+ sha256_final(&ctx, digest);
|
||||
+ return (unsigned char *)digest;
|
||||
+}
|
||||
+
|
||||
+/* Code from here onwards comes from https://github.com/B-Con/crypto-algorithms
|
||||
+ and was written by Brad Conte (brad@bradconte.com), to whom all credit is given.
|
||||
+
|
||||
+ This code is in the public domain, and the copyright notice at the head of this
|
||||
+ file does not apply to it.
|
||||
+*/
|
||||
+
|
||||
+
|
||||
+/****************************** MACROS ******************************/
|
||||
+#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
|
||||
+#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
|
||||
+
|
||||
+#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
+#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
+#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
|
||||
+#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
|
||||
+#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
|
||||
+#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
|
||||
+
|
||||
+/**************************** VARIABLES *****************************/
|
||||
+static const WORD k[64] = {
|
||||
+ 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||
+ 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||
+ 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||
+ 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||
+ 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||
+ 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||
+ 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||
+ 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
+};
|
||||
+
|
||||
+/*********************** FUNCTION DEFINITIONS ***********************/
|
||||
+static void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
|
||||
+{
|
||||
+ WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
|
||||
+
|
||||
+ for (i = 0, j = 0; i < 16; ++i, j += 4)
|
||||
+ m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
|
||||
+ for ( ; i < 64; ++i)
|
||||
+ m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
+
|
||||
+ a = ctx->state[0];
|
||||
+ b = ctx->state[1];
|
||||
+ c = ctx->state[2];
|
||||
+ d = ctx->state[3];
|
||||
+ e = ctx->state[4];
|
||||
+ f = ctx->state[5];
|
||||
+ g = ctx->state[6];
|
||||
+ h = ctx->state[7];
|
||||
+
|
||||
+ for (i = 0; i < 64; ++i)
|
||||
+ {
|
||||
+ t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
|
||||
+ t2 = EP0(a) + MAJ(a,b,c);
|
||||
+ h = g;
|
||||
+ g = f;
|
||||
+ f = e;
|
||||
+ e = d + t1;
|
||||
+ d = c;
|
||||
+ c = b;
|
||||
+ b = a;
|
||||
+ a = t1 + t2;
|
||||
+ }
|
||||
+
|
||||
+ ctx->state[0] += a;
|
||||
+ ctx->state[1] += b;
|
||||
+ ctx->state[2] += c;
|
||||
+ ctx->state[3] += d;
|
||||
+ ctx->state[4] += e;
|
||||
+ ctx->state[5] += f;
|
||||
+ ctx->state[6] += g;
|
||||
+ ctx->state[7] += h;
|
||||
+}
|
||||
+
|
||||
+static void sha256_init(SHA256_CTX *ctx)
|
||||
+{
|
||||
+ ctx->datalen = 0;
|
||||
+ ctx->bitlen = 0;
|
||||
+ ctx->state[0] = 0x6a09e667;
|
||||
+ ctx->state[1] = 0xbb67ae85;
|
||||
+ ctx->state[2] = 0x3c6ef372;
|
||||
+ ctx->state[3] = 0xa54ff53a;
|
||||
+ ctx->state[4] = 0x510e527f;
|
||||
+ ctx->state[5] = 0x9b05688c;
|
||||
+ ctx->state[6] = 0x1f83d9ab;
|
||||
+ ctx->state[7] = 0x5be0cd19;
|
||||
+}
|
||||
+
|
||||
+static void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
|
||||
+{
|
||||
+ WORD i;
|
||||
+
|
||||
+ for (i = 0; i < len; ++i)
|
||||
+ {
|
||||
+ ctx->data[ctx->datalen] = data[i];
|
||||
+ ctx->datalen++;
|
||||
+ if (ctx->datalen == 64) {
|
||||
+ sha256_transform(ctx, ctx->data);
|
||||
+ ctx->bitlen += 512;
|
||||
+ ctx->datalen = 0;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
||||
+{
|
||||
+ WORD i;
|
||||
+
|
||||
+ i = ctx->datalen;
|
||||
+
|
||||
+ // Pad whatever data is left in the buffer.
|
||||
+ if (ctx->datalen < 56)
|
||||
+ {
|
||||
+ ctx->data[i++] = 0x80;
|
||||
+ while (i < 56)
|
||||
+ ctx->data[i++] = 0x00;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ctx->data[i++] = 0x80;
|
||||
+ while (i < 64)
|
||||
+ ctx->data[i++] = 0x00;
|
||||
+ sha256_transform(ctx, ctx->data);
|
||||
+ memset(ctx->data, 0, 56);
|
||||
+ }
|
||||
+
|
||||
+ // Append to the padding the total message's length in bits and transform.
|
||||
+ ctx->bitlen += ctx->datalen * 8;
|
||||
+ ctx->data[63] = ctx->bitlen;
|
||||
+ ctx->data[62] = ctx->bitlen >> 8;
|
||||
+ ctx->data[61] = ctx->bitlen >> 16;
|
||||
+ ctx->data[60] = ctx->bitlen >> 24;
|
||||
+ ctx->data[59] = ctx->bitlen >> 32;
|
||||
+ ctx->data[58] = ctx->bitlen >> 40;
|
||||
+ ctx->data[57] = ctx->bitlen >> 48;
|
||||
+ ctx->data[56] = ctx->bitlen >> 56;
|
||||
+ sha256_transform(ctx, ctx->data);
|
||||
+
|
||||
+ // Since this implementation uses little endian byte ordering and SHA uses big endian,
|
||||
+ // reverse all the bytes when copying the final state to the output hash.
|
||||
+ for (i = 0; i < 4; ++i)
|
||||
+ {
|
||||
+ hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index b078b59..d413f58 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -335,55 +335,6 @@ unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *h
|
||||
return ansp;
|
||||
}
|
||||
|
||||
-/* CRC the question section. This is used to safely detect query
|
||||
- retransmission and to detect answers to questions we didn't ask, which
|
||||
- might be poisoning attacks. Note that we decode the name rather
|
||||
- than CRC the raw bytes, since replies might be compressed differently.
|
||||
- We ignore case in the names for the same reason. Return all-ones
|
||||
- if there is not question section. */
|
||||
-#ifndef HAVE_DNSSEC
|
||||
-unsigned int questions_crc(struct dns_header *header, size_t plen, char *name)
|
||||
-{
|
||||
- int q;
|
||||
- unsigned int crc = 0xffffffff;
|
||||
- unsigned char *p1, *p = (unsigned char *)(header+1);
|
||||
-
|
||||
- for (q = ntohs(header->qdcount); q != 0; q--)
|
||||
- {
|
||||
- if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
- return crc; /* bad packet */
|
||||
-
|
||||
- for (p1 = (unsigned char *)name; *p1; p1++)
|
||||
- {
|
||||
- int i = 8;
|
||||
- char c = *p1;
|
||||
-
|
||||
- if (c >= 'A' && c <= 'Z')
|
||||
- c += 'a' - 'A';
|
||||
-
|
||||
- crc ^= c << 24;
|
||||
- while (i--)
|
||||
- crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
|
||||
- }
|
||||
-
|
||||
- /* CRC the class and type as well */
|
||||
- for (p1 = p; p1 < p+4; p1++)
|
||||
- {
|
||||
- int i = 8;
|
||||
- crc ^= *p1 << 24;
|
||||
- while (i--)
|
||||
- crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
|
||||
- }
|
||||
-
|
||||
- p += 4;
|
||||
- if (!CHECK_LEN(header, p, plen, 0))
|
||||
- return crc; /* bad packet */
|
||||
- }
|
||||
-
|
||||
- return crc;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *pheader, size_t hlen)
|
||||
{
|
||||
unsigned char *ansp = skip_questions(header, plen);
|
||||
--
|
||||
2.26.2
|
||||
|
61
SOURCES/dnsmasq-2.79-CVE-2020-25686-2.patch
Normal file
61
SOURCES/dnsmasq-2.79-CVE-2020-25686-2.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From e9db3fdf55cdf3175d96db90313c33f848985960 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Fri, 4 Dec 2020 18:35:11 +0000
|
||||
Subject: [PATCH] Small cleanups in frec_src datastucture handling.
|
||||
|
||||
---
|
||||
src/forward.c | 22 +++++++++++++---------
|
||||
1 file changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index 25ad8b1..c496f86 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -364,7 +364,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
if (!daemon->free_frec_src &&
|
||||
daemon->frec_src_count < daemon->ftabsize &&
|
||||
(daemon->free_frec_src = whine_malloc(sizeof(struct frec_src))))
|
||||
- daemon->frec_src_count++;
|
||||
+ {
|
||||
+ daemon->frec_src_count++;
|
||||
+ daemon->free_frec_src->next = NULL;
|
||||
+ }
|
||||
|
||||
/* If we've been spammed with many duplicates, just drop the query. */
|
||||
if (daemon->free_frec_src)
|
||||
@@ -401,6 +404,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
forward->frec_src.orig_id = ntohs(header->id);
|
||||
forward->frec_src.dest = *dst_addr;
|
||||
forward->frec_src.iface = dst_iface;
|
||||
+ forward->frec_src.next = NULL;
|
||||
forward->new_id = get_id();
|
||||
forward->fd = udpfd;
|
||||
memcpy(forward->hash, hash, HASH_SIZE);
|
||||
@@ -2262,16 +2266,16 @@ void free_rfd(struct randfd *rfd)
|
||||
|
||||
static void free_frec(struct frec *f)
|
||||
{
|
||||
- struct frec_src *src, *tmp;
|
||||
-
|
||||
- /* add back to freelist of not the record builtin to every frec. */
|
||||
- for (src = f->frec_src.next; src; src = tmp)
|
||||
+ struct frec_src *last;
|
||||
+
|
||||
+ /* add back to freelist if not the record builtin to every frec. */
|
||||
+ for (last = f->frec_src.next; last && last->next; last = last->next) ;
|
||||
+ if (last)
|
||||
{
|
||||
- tmp = src->next;
|
||||
- src->next = daemon->free_frec_src;
|
||||
- daemon->free_frec_src = src;
|
||||
+ last->next = daemon->free_frec_src;
|
||||
+ daemon->free_frec_src = f->frec_src.next;
|
||||
}
|
||||
-
|
||||
+
|
||||
f->frec_src.next = NULL;
|
||||
free_rfd(f->rfd4);
|
||||
f->rfd4 = NULL;
|
||||
--
|
||||
2.26.2
|
||||
|
327
SOURCES/dnsmasq-2.79-CVE-2020-25686.patch
Normal file
327
SOURCES/dnsmasq-2.79-CVE-2020-25686.patch
Normal file
@ -0,0 +1,327 @@
|
||||
From 7d98347aeeb575a022ffae630ee02da215b6f37b Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Wed, 18 Nov 2020 18:34:55 +0000
|
||||
Subject: [PATCH 4/4] Handle multiple identical near simultaneous DNS queries
|
||||
better.
|
||||
|
||||
Previously, such queries would all be forwarded
|
||||
independently. This is, in theory, inefficent but in practise
|
||||
not a problem, _except_ that is means that an answer for any
|
||||
of the forwarded queries will be accepted and cached.
|
||||
An attacker can send a query multiple times, and for each repeat,
|
||||
another {port, ID} becomes capable of accepting the answer he is
|
||||
sending in the blind, to random IDs and ports. The chance of a
|
||||
succesful attack is therefore multiplied by the number of repeats
|
||||
of the query. The new behaviour detects repeated queries and
|
||||
merely stores the clients sending repeats so that when the
|
||||
first query completes, the answer can be sent to all the
|
||||
clients who asked. Refer: CERT VU#434904.
|
||||
---
|
||||
src/dnsmasq.h | 19 ++++---
|
||||
src/forward.c | 141 ++++++++++++++++++++++++++++++++++++++++++--------
|
||||
2 files changed, 132 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index f31503d..6744e2b 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -613,21 +613,26 @@ struct hostsfile {
|
||||
#define FREC_DO_QUESTION 64
|
||||
#define FREC_ADDED_PHEADER 128
|
||||
#define FREC_TEST_PKTSZ 256
|
||||
-#define FREC_HAS_EXTRADATA 512
|
||||
+#define FREC_HAS_EXTRADATA 512
|
||||
+#define FREC_HAS_PHEADER 1024
|
||||
|
||||
#define HASH_SIZE 32 /* SHA-256 digest size */
|
||||
|
||||
struct frec {
|
||||
- union mysockaddr source;
|
||||
- struct all_addr dest;
|
||||
+ struct frec_src {
|
||||
+ union mysockaddr source;
|
||||
+ struct all_addr dest;
|
||||
+ unsigned int iface, log_id;
|
||||
+ unsigned short orig_id;
|
||||
+ struct frec_src *next;
|
||||
+ } frec_src;
|
||||
struct server *sentto; /* NULL means free */
|
||||
struct randfd *rfd4;
|
||||
#ifdef HAVE_IPV6
|
||||
struct randfd *rfd6;
|
||||
#endif
|
||||
- unsigned int iface;
|
||||
- unsigned short orig_id, new_id;
|
||||
- int log_id, fd, forwardall, flags;
|
||||
+ unsigned short new_id;
|
||||
+ int fd, forwardall, flags;
|
||||
time_t time;
|
||||
unsigned char *hash[HASH_SIZE];
|
||||
#ifdef HAVE_DNSSEC
|
||||
@@ -1033,6 +1038,8 @@ extern struct daemon {
|
||||
#endif
|
||||
unsigned int local_answer, queries_forwarded, auth_answer;
|
||||
struct frec *frec_list;
|
||||
+ struct frec_src *free_frec_src;
|
||||
+ int frec_src_count;
|
||||
struct serverfd *sfds;
|
||||
struct irec *interfaces;
|
||||
struct listener *listeners;
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index 7ffcaf7..db378a5 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -20,6 +20,8 @@ static struct frec *lookup_frec(unsigned short id, int fd, int family, void *has
|
||||
static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||
union mysockaddr *addr,
|
||||
void *hash);
|
||||
+static struct frec *lookup_frec_by_query(void *hash, unsigned int flags);
|
||||
+
|
||||
static unsigned short get_id(void);
|
||||
static void free_frec(struct frec *f);
|
||||
|
||||
@@ -238,15 +240,28 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
int type = SERV_DO_DNSSEC, norebind = 0;
|
||||
struct all_addr *addrp = NULL;
|
||||
unsigned int flags = 0;
|
||||
+ unsigned int fwd_flags = 0;
|
||||
struct server *start = NULL;
|
||||
void *hash = hash_questions(header, plen, daemon->namebuff);
|
||||
#ifdef HAVE_DNSSEC
|
||||
int do_dnssec = 0;
|
||||
#endif
|
||||
- unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
+ unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
+ unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
|
||||
|
||||
(void)do_bit;
|
||||
-
|
||||
+
|
||||
+ if (header->hb4 & HB4_CD)
|
||||
+ fwd_flags |= FREC_CHECKING_DISABLED;
|
||||
+ if (ad_reqd)
|
||||
+ fwd_flags |= FREC_AD_QUESTION;
|
||||
+ if (oph)
|
||||
+ fwd_flags |= FREC_HAS_PHEADER;
|
||||
+#ifdef HAVE_DNSSEC
|
||||
+ if (do_bit)
|
||||
+ fwd_flags |= FREC_DO_QUESTION;
|
||||
+#endif
|
||||
+
|
||||
/* may be no servers available. */
|
||||
if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash)))
|
||||
{
|
||||
@@ -322,6 +337,39 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
}
|
||||
else
|
||||
{
|
||||
+ /* Query from new source, but the same query may be in progress
|
||||
+ from another source. If so, just add this client to the
|
||||
+ list that will get the reply.
|
||||
+
|
||||
+ Note that is the EDNS client subnet option is in use, we can't do this,
|
||||
+ as the clients (and therefore query EDNS options) will be different
|
||||
+ for each query. The EDNS subnet code has checks to avoid
|
||||
+ attacks in this case. */
|
||||
+ if (!option_bool(OPT_CLIENT_SUBNET) && (forward = lookup_frec_by_query(hash, fwd_flags)))
|
||||
+ {
|
||||
+ /* Note whine_malloc() zeros memory. */
|
||||
+ if (!daemon->free_frec_src &&
|
||||
+ daemon->frec_src_count < daemon->ftabsize &&
|
||||
+ (daemon->free_frec_src = whine_malloc(sizeof(struct frec_src))))
|
||||
+ daemon->frec_src_count++;
|
||||
+
|
||||
+ /* If we've been spammed with many duplicates, just drop the query. */
|
||||
+ if (daemon->free_frec_src)
|
||||
+ {
|
||||
+ struct frec_src *new = daemon->free_frec_src;
|
||||
+ daemon->free_frec_src = new->next;
|
||||
+ new->next = forward->frec_src.next;
|
||||
+ forward->frec_src.next = new;
|
||||
+ new->orig_id = ntohs(header->id);
|
||||
+ new->source = *udpaddr;
|
||||
+ new->dest = *dst_addr;
|
||||
+ new->log_id = daemon->log_id;
|
||||
+ new->iface = dst_iface;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
if (gotname)
|
||||
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
|
||||
|
||||
@@ -329,22 +377,22 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
do_dnssec = type & SERV_DO_DNSSEC;
|
||||
#endif
|
||||
type &= ~SERV_DO_DNSSEC;
|
||||
-
|
||||
+
|
||||
if (daemon->servers && !flags)
|
||||
forward = get_new_frec(now, NULL, 0);
|
||||
/* table full - flags == 0, return REFUSED */
|
||||
|
||||
if (forward)
|
||||
{
|
||||
- forward->source = *udpaddr;
|
||||
- forward->dest = *dst_addr;
|
||||
- forward->iface = dst_iface;
|
||||
- forward->orig_id = ntohs(header->id);
|
||||
+ forward->frec_src.source = *udpaddr;
|
||||
+ forward->frec_src.orig_id = ntohs(header->id);
|
||||
+ forward->frec_src.dest = *dst_addr;
|
||||
+ forward->frec_src.iface = dst_iface;
|
||||
forward->new_id = get_id();
|
||||
forward->fd = udpfd;
|
||||
memcpy(forward->hash, hash, HASH_SIZE);
|
||||
forward->forwardall = 0;
|
||||
- forward->flags = 0;
|
||||
+ forward->flags = fwd_flags;
|
||||
if (norebind)
|
||||
forward->flags |= FREC_NOREBIND;
|
||||
if (header->hb4 & HB4_CD)
|
||||
@@ -400,9 +448,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
unsigned char *pheader;
|
||||
|
||||
/* If a query is retried, use the log_id for the retry when logging the answer. */
|
||||
- forward->log_id = daemon->log_id;
|
||||
+ forward->frec_src.log_id = daemon->log_id;
|
||||
|
||||
- plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
|
||||
+ plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &subnet);
|
||||
|
||||
if (subnet)
|
||||
forward->flags |= FREC_HAS_SUBNET;
|
||||
@@ -539,7 +587,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
return 1;
|
||||
|
||||
/* could not send on, prepare to return */
|
||||
- header->id = htons(forward->orig_id);
|
||||
+ header->id = htons(forward->frec_src.orig_id);
|
||||
free_frec(forward); /* cancel */
|
||||
}
|
||||
|
||||
@@ -774,8 +822,8 @@ void reply_query(int fd, int family, time_t now)
|
||||
|
||||
/* log_query gets called indirectly all over the place, so
|
||||
pass these in global variables - sorry. */
|
||||
- daemon->log_display_id = forward->log_id;
|
||||
- daemon->log_source_addr = &forward->source;
|
||||
+ daemon->log_display_id = forward->frec_src.log_id;
|
||||
+ daemon->log_source_addr = &forward->frec_src.source;
|
||||
|
||||
if (daemon->ignore_addr && RCODE(header) == NOERROR &&
|
||||
check_for_ignored_address(header, n, daemon->ignore_addr))
|
||||
@@ -978,6 +1026,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
#ifdef HAVE_IPV6
|
||||
new->rfd6 = NULL;
|
||||
#endif
|
||||
+ new->frec_src.next = NULL;
|
||||
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY);
|
||||
|
||||
new->dependent = forward; /* to find query awaiting new one. */
|
||||
@@ -1099,9 +1148,11 @@ void reply_query(int fd, int family, time_t now)
|
||||
|
||||
if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
|
||||
forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
|
||||
- forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
|
||||
+ forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->frec_src.source)))
|
||||
{
|
||||
- header->id = htons(forward->orig_id);
|
||||
+ struct frec_src *src;
|
||||
+
|
||||
+ header->id = htons(forward->frec_src.orig_id);
|
||||
header->hb4 |= HB4_RA; /* recursion if available */
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
|
||||
@@ -1116,9 +1167,22 @@ void reply_query(int fd, int family, time_t now)
|
||||
nn = resize_packet(header, nn, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
- send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
|
||||
- &forward->source, &forward->dest, forward->iface);
|
||||
+ for (src = &forward->frec_src; src; src = src->next)
|
||||
+ {
|
||||
+ header->id = htons(src->orig_id);
|
||||
+
|
||||
+ send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
|
||||
+ &src->source, &src->dest, src->iface);
|
||||
+
|
||||
+ if (option_bool(OPT_EXTRALOG) && src != &forward->frec_src)
|
||||
+ {
|
||||
+ daemon->log_display_id = src->log_id;
|
||||
+ daemon->log_source_addr = &src->source;
|
||||
+ log_query(F_UPSTREAM, "query", NULL, "duplicate");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+
|
||||
free_frec(forward); /* cancel */
|
||||
}
|
||||
}
|
||||
@@ -2053,6 +2117,17 @@ void free_rfd(struct randfd *rfd)
|
||||
|
||||
static void free_frec(struct frec *f)
|
||||
{
|
||||
+ struct frec_src *src, *tmp;
|
||||
+
|
||||
+ /* add back to freelist of not the record builtin to every frec. */
|
||||
+ for (src = f->frec_src.next; src; src = tmp)
|
||||
+ {
|
||||
+ tmp = src->next;
|
||||
+ src->next = daemon->free_frec_src;
|
||||
+ daemon->free_frec_src = src;
|
||||
+ }
|
||||
+
|
||||
+ f->frec_src.next = NULL;
|
||||
free_rfd(f->rfd4);
|
||||
f->rfd4 = NULL;
|
||||
f->sentto = NULL;
|
||||
@@ -2196,17 +2271,39 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
|
||||
void *hash)
|
||||
{
|
||||
struct frec *f;
|
||||
+ struct frec_src *src;
|
||||
+
|
||||
+ for (f = daemon->frec_list; f; f = f->next)
|
||||
+ if (f->sentto &&
|
||||
+ !(f->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) &&
|
||||
+ memcmp(hash, f->hash, HASH_SIZE) == 0)
|
||||
+ for (src = &f->frec_src; src; src = src->next)
|
||||
+ if (src->orig_id == id &&
|
||||
+ sockaddr_isequal(&src->source, addr))
|
||||
+ return f;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static struct frec *lookup_frec_by_query(void *hash, unsigned int flags)
|
||||
+{
|
||||
+ struct frec *f;
|
||||
+
|
||||
+ /* FREC_DNSKEY and FREC_DS_QUERY are never set in flags, so the test below
|
||||
+ ensures that no frec created for internal DNSSEC query can be returned here. */
|
||||
+
|
||||
+#define FLAGMASK (FREC_CHECKING_DISABLED | FREC_AD_QUESTION | FREC_DO_QUESTION \
|
||||
+ | FREC_HAS_PHEADER | FREC_DNSKEY_QUERY | FREC_DS_QUERY)
|
||||
|
||||
for(f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto &&
|
||||
- f->orig_id == id &&
|
||||
- memcmp(hash, f->hash, HASH_SIZE) == 0 &&
|
||||
- sockaddr_isequal(&f->source, addr))
|
||||
+ (f->flags & FLAGMASK) == flags &&
|
||||
+ memcmp(hash, f->hash, HASH_SIZE) == 0)
|
||||
return f;
|
||||
-
|
||||
+
|
||||
return NULL;
|
||||
}
|
||||
-
|
||||
+
|
||||
/* Send query packet again, if we can. */
|
||||
void resend_query()
|
||||
{
|
||||
--
|
||||
2.26.2
|
||||
|
107
SOURCES/dnsmasq-2.79-alternative-lease.patch
Normal file
107
SOURCES/dnsmasq-2.79-alternative-lease.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 268080fc19990711a1d1e1acd68a50aa2f6cb5fb Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Fri, 17 Sep 2021 20:12:21 +0200
|
||||
Subject: [PATCH] Offer alternative DHCPv6 address if requested is taken
|
||||
|
||||
In some cases multiple requests might arrive from single DUID. It may
|
||||
happen just one address is offered to different IAID requests. When
|
||||
the first request confirms lease, another would be offered alternative
|
||||
address instead of address in use error.
|
||||
|
||||
Includes check on such Rapid commit equivalents and returns NotOnLink
|
||||
error, required by RFC 8145, if requested address were not on any
|
||||
supported prefix.
|
||||
---
|
||||
src/rfc3315.c | 39 ++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 28 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c
|
||||
index 5c2ff97..d1534ad 100644
|
||||
--- a/src/rfc3315.c
|
||||
+++ b/src/rfc3315.c
|
||||
@@ -614,7 +614,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
|
||||
case DHCP6SOLICIT:
|
||||
{
|
||||
- int address_assigned = 0;
|
||||
+ int address_assigned = 0, ia_invalid = 0;
|
||||
/* tags without all prefix-class tags */
|
||||
struct dhcp_netid *solicit_tags;
|
||||
struct dhcp_context *c;
|
||||
@@ -697,6 +697,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
get_context_tag(state, c);
|
||||
address_assigned = 1;
|
||||
}
|
||||
+ else
|
||||
+ ia_invalid++;
|
||||
}
|
||||
|
||||
/* Suggest configured address(es) */
|
||||
@@ -782,11 +784,26 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
tagif = add_options(state, 0);
|
||||
}
|
||||
else
|
||||
- {
|
||||
+ {
|
||||
+ char *errmsg;
|
||||
/* no address, return error */
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
- put_opt6_short(DHCP6NOADDRS);
|
||||
- put_opt6_string(_("no addresses available"));
|
||||
+ if (state->lease_allocate && ia_invalid)
|
||||
+ {
|
||||
+ /* RFC 8415, Section 18.3.2:
|
||||
+ If any of the prefixes of the included addresses are not
|
||||
+ appropriate for the link to which the client is connected,
|
||||
+ the server MUST return the IA to the client with a Status
|
||||
+ Code option with the value NotOnLink. */
|
||||
+ put_opt6_short(DHCP6NOTONLINK);
|
||||
+ errmsg = _("not on link");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ put_opt6_short(DHCP6NOADDRS);
|
||||
+ errmsg = _("no addresses available");
|
||||
+ }
|
||||
+ put_opt6_string(errmsg);
|
||||
end_opt6(o1);
|
||||
|
||||
/* Some clients will ask repeatedly when we're not giving
|
||||
@@ -795,7 +812,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_RA_STATELESS))
|
||||
{
|
||||
- log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
|
||||
+ log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, errmsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -831,7 +848,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
/* If we get a request with an IA_*A without addresses, treat it exactly like
|
||||
a SOLICT with rapid commit set. */
|
||||
save_counter(start);
|
||||
- goto request_no_address;
|
||||
+ goto request_no_address;
|
||||
}
|
||||
|
||||
o = build_ia(state, &t1cntr);
|
||||
@@ -861,11 +878,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
else if (!check_address(state, &req_addr))
|
||||
{
|
||||
- /* Address leased to another DUID/IAID */
|
||||
- o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
- put_opt6_short(DHCP6UNSPEC);
|
||||
- put_opt6_string(_("address in use"));
|
||||
- end_opt6(o1);
|
||||
+ /* Address leased to another DUID/IAID.
|
||||
+ Find another address for the client, treat it exactly like
|
||||
+ a SOLICT with rapid commit set. */
|
||||
+ save_counter(start);
|
||||
+ goto request_no_address;
|
||||
}
|
||||
else
|
||||
{
|
||||
--
|
||||
2.31.1
|
||||
|
79
SOURCES/dnsmasq-2.79-mixed-family-failed.patch
Normal file
79
SOURCES/dnsmasq-2.79-mixed-family-failed.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From 4348c43be45d20aba87ee5564ecdde10aff7e5e7 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Fri, 22 Jan 2021 16:49:12 +0000
|
||||
Subject: [PATCH] Move fd into frec_src, fixes
|
||||
15b60ddf935a531269bb8c68198de012a4967156
|
||||
|
||||
If identical queries from IPv4 and IPv6 sources are combined by the
|
||||
new code added in 15b60ddf935a531269bb8c68198de012a4967156 then replies
|
||||
can end up being sent via the wrong family of socket. The ->fd
|
||||
should be per query, not per-question.
|
||||
|
||||
In bind-interfaces mode, this could also result in replies being sent
|
||||
via the wrong socket even when IPv4/IPV6 issues are not in play.
|
||||
|
||||
(cherry picked from commit 04490bf622ac84891aad6f2dd2edf83725decdee)
|
||||
|
||||
Fix for 12af2b171de0d678d98583e2190789e544440e02
|
||||
|
||||
(cherry picked from commit 3f535da79e7a42104543ef5c7b5fa2bed819a78b)
|
||||
---
|
||||
src/dnsmasq.h | 3 ++-
|
||||
src/forward.c | 5 +++--
|
||||
2 files changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index f3bbb4e..e7e1693 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -632,6 +632,7 @@ struct frec {
|
||||
union mysockaddr source;
|
||||
struct all_addr dest;
|
||||
unsigned int iface, log_id;
|
||||
+ int fd;
|
||||
unsigned short orig_id;
|
||||
struct frec_src *next;
|
||||
} frec_src;
|
||||
@@ -641,7 +642,7 @@ struct frec {
|
||||
struct randfd *rfd6;
|
||||
#endif
|
||||
unsigned short new_id;
|
||||
- int fd, forwardall, flags;
|
||||
+ int forwardall, flags;
|
||||
time_t time;
|
||||
unsigned char *hash[HASH_SIZE];
|
||||
#ifdef HAVE_DNSSEC
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index 9d249c0..82dd850 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -368,6 +368,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
new->dest = *dst_addr;
|
||||
new->log_id = daemon->log_id;
|
||||
new->iface = dst_iface;
|
||||
+ new->fd = udpfd;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -392,8 +393,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
forward->frec_src.dest = *dst_addr;
|
||||
forward->frec_src.iface = dst_iface;
|
||||
forward->frec_src.next = NULL;
|
||||
+ forward->frec_src.fd = udpfd;
|
||||
forward->new_id = get_id();
|
||||
- forward->fd = udpfd;
|
||||
memcpy(forward->hash, hash, HASH_SIZE);
|
||||
forward->forwardall = 0;
|
||||
forward->flags = fwd_flags;
|
||||
@@ -1175,7 +1176,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
{
|
||||
header->id = htons(src->orig_id);
|
||||
|
||||
- send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
|
||||
+ send_from(src->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
|
||||
&src->source, &src->dest, src->iface);
|
||||
|
||||
if (option_bool(OPT_EXTRALOG) && src != &forward->frec_src)
|
||||
--
|
||||
2.26.2
|
||||
|
99
SOURCES/dnsmasq-2.79-server-domain-fixup.patch
Normal file
99
SOURCES/dnsmasq-2.79-server-domain-fixup.patch
Normal file
@ -0,0 +1,99 @@
|
||||
From 4c5cbdfb82e668268a5f3713fe119fb077667c8e Mon Sep 17 00:00:00 2001
|
||||
From: rpm-build <rpm-build>
|
||||
Date: Mon, 22 Aug 2022 21:59:42 +0200
|
||||
Subject: [PATCH] Ensure also server_domains_cleanup is called always
|
||||
|
||||
Fixes issue in patch dnsmasq-2.79-server-domain-rh1919894.patch.
|
||||
|
||||
When /etc/resolv.conf is changed, dnsmasq reloads used servers. But it
|
||||
does not call cleanup of server domains in this case. It might cause
|
||||
serv_domain->last_server to become non-null, but pointing released
|
||||
server. Ensure it is checked before any cleanup_servers() action always
|
||||
and from all other places, like dbus setting.
|
||||
|
||||
Caused unending loop in forward_query function, rhbz#2106361.
|
||||
---
|
||||
src/network.c | 49 +++++++++++++++++++++++++------------------------
|
||||
1 file changed, 25 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/src/network.c b/src/network.c
|
||||
index 4d140bb..96668fb 100644
|
||||
--- a/src/network.c
|
||||
+++ b/src/network.c
|
||||
@@ -1402,10 +1402,35 @@ void mark_servers(int flag)
|
||||
}
|
||||
}
|
||||
|
||||
+static void server_domains_cleanup(void)
|
||||
+{
|
||||
+ struct server_domain *sd, *tmp, **up;
|
||||
+
|
||||
+ /* unlink and free anything still marked. */
|
||||
+ for (up = &daemon->server_domains, sd=*up; sd; sd = tmp)
|
||||
+ {
|
||||
+ tmp = sd->next;
|
||||
+ if (sd->flags & SERV_MARK)
|
||||
+ {
|
||||
+ *up = sd->next;
|
||||
+ if (sd->domain)
|
||||
+ free(sd->domain);
|
||||
+ free(sd);
|
||||
+ }
|
||||
+ else {
|
||||
+ up = &sd->next;
|
||||
+ if (sd->last_server && (sd->last_server->flags & SERV_MARK))
|
||||
+ sd->last_server = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void cleanup_servers(void)
|
||||
{
|
||||
struct server *serv, *tmp, **up;
|
||||
|
||||
+ server_domains_cleanup();
|
||||
+
|
||||
/* unlink and free anything still marked. */
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
{
|
||||
@@ -1428,29 +1453,6 @@ void cleanup_servers(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
-void server_domains_cleanup(void)
|
||||
-{
|
||||
- struct server_domain *sd, *tmp, **up;
|
||||
-
|
||||
- /* unlink and free anything still marked. */
|
||||
- for (up = &daemon->server_domains, sd=*up; sd; sd = tmp)
|
||||
- {
|
||||
- tmp = sd->next;
|
||||
- if (sd->flags & SERV_MARK)
|
||||
- {
|
||||
- *up = sd->next;
|
||||
- if (sd->domain)
|
||||
- free(sd->domain);
|
||||
- free(sd);
|
||||
- }
|
||||
- else {
|
||||
- up = &sd->next;
|
||||
- if (sd->last_server && (sd->last_server->flags & SERV_MARK))
|
||||
- sd->last_server = NULL;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void add_update_server(int flags,
|
||||
union mysockaddr *addr,
|
||||
union mysockaddr *source_addr,
|
||||
@@ -1739,7 +1741,6 @@ void check_servers(void)
|
||||
up = &sfd->next;
|
||||
}
|
||||
|
||||
- server_domains_cleanup();
|
||||
cleanup_servers();
|
||||
}
|
||||
|
||||
--
|
||||
2.37.2
|
||||
|
473
SOURCES/dnsmasq-2.79-server-domain-rh1919894.patch
Normal file
473
SOURCES/dnsmasq-2.79-server-domain-rh1919894.patch
Normal file
@ -0,0 +1,473 @@
|
||||
From b15c92e5d793c9767591dbf8910bf3466aba92ee Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Mon, 19 Apr 2021 13:56:23 +0200
|
||||
Subject: [PATCH] Use load-balancing also for --server=/domains/
|
||||
|
||||
Do not (yet) move servers to server_domain structure. Instead use
|
||||
separate server_domains to store just last_server and requests count and
|
||||
time.
|
||||
|
||||
Introduces domain information duplicity, but minimizes required changes
|
||||
to daemon->servers usage.
|
||||
|
||||
Optimize server domain record
|
||||
|
||||
Set pointer to domain record when struct server is created. When
|
||||
searching for domain pointer, use this pointer to make it quick.
|
||||
---
|
||||
src/dnsmasq.h | 18 +++++++--
|
||||
src/forward.c | 54 ++++++++++++++++-----------
|
||||
src/network.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
src/option.c | 5 +++
|
||||
4 files changed, 147 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index 4beef35..27ff86a 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -531,6 +531,17 @@ struct randfd_list {
|
||||
struct randfd_list *next;
|
||||
};
|
||||
|
||||
+/* contains domain specific set of servers.
|
||||
+ * If domain is NULL, just normal servers. */
|
||||
+struct server_domain {
|
||||
+ char *domain;
|
||||
+ struct server *last_server;
|
||||
+ time_t forwardtime;
|
||||
+ int forwardcount;
|
||||
+ unsigned int flags; /* server.flags alternative */
|
||||
+ struct server_domain *next;
|
||||
+};
|
||||
+
|
||||
struct server {
|
||||
union mysockaddr addr, source_addr;
|
||||
char interface[IF_NAMESIZE+1];
|
||||
@@ -543,6 +554,7 @@ struct server {
|
||||
#ifdef HAVE_LOOP
|
||||
u32 uid;
|
||||
#endif
|
||||
+ struct server_domain *serv_domain;
|
||||
struct server *next;
|
||||
};
|
||||
|
||||
@@ -995,6 +1007,7 @@ extern struct daemon {
|
||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
||||
struct bogus_addr *bogus_addr, *ignore_addr;
|
||||
struct server *servers;
|
||||
+ struct server_domain *server_domains;
|
||||
struct ipsets *ipsets;
|
||||
int log_fac; /* log facility */
|
||||
char *log_file; /* optional log file */
|
||||
@@ -1061,9 +1074,6 @@ extern struct daemon {
|
||||
struct serverfd *sfds;
|
||||
struct irec *interfaces;
|
||||
struct listener *listeners;
|
||||
- struct server *last_server;
|
||||
- time_t forwardtime;
|
||||
- int forwardcount;
|
||||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
int fd_save; /* " " */
|
||||
@@ -1319,6 +1329,8 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
||||
int label_exception(int index, int family, struct all_addr *addr);
|
||||
int fix_fd(int fd);
|
||||
int tcp_interface(int fd, int af);
|
||||
+struct server_domain *server_domain_find_domain(const char *domain);
|
||||
+struct server_domain *server_domain_new(struct server *serv);
|
||||
#ifdef HAVE_IPV6
|
||||
int set_ipv6pktinfo(int fd);
|
||||
#endif
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index 11e0310..d8e845a 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -109,7 +109,8 @@ int send_from(int fd, int nowild, char *packet, size_t len,
|
||||
}
|
||||
|
||||
static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigned int qtype,
|
||||
- char *qdomain, int *type, char **domain, int *norebind)
|
||||
+ char *qdomain, int *type, char **domain, int *norebind,
|
||||
+ struct server_domain **serv_domain)
|
||||
|
||||
{
|
||||
/* If the query ends in the domain in one of our servers, set
|
||||
@@ -121,6 +122,9 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
struct server *serv;
|
||||
unsigned int flags = 0;
|
||||
|
||||
+ if (serv_domain)
|
||||
+ *serv_domain = NULL;
|
||||
+
|
||||
for (serv = daemon->servers; serv; serv=serv->next)
|
||||
if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
|
||||
continue;
|
||||
@@ -181,6 +185,8 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
{
|
||||
*type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
|
||||
*domain = serv->domain;
|
||||
+ if (serv_domain)
|
||||
+ *serv_domain = serv->serv_domain;
|
||||
matchlen = domainlen;
|
||||
if (serv->flags & SERV_NO_ADDR)
|
||||
flags = F_NXDOMAIN;
|
||||
@@ -228,6 +234,8 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
*type = 0; /* use normal servers for this domain */
|
||||
*domain = NULL;
|
||||
}
|
||||
+ if (serv_domain && !*serv_domain)
|
||||
+ *serv_domain = server_domain_find_domain(*domain);
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -242,6 +250,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
unsigned int flags = 0;
|
||||
unsigned int fwd_flags = 0;
|
||||
struct server *start = NULL;
|
||||
+ struct server_domain *sd = NULL;
|
||||
void *hash = hash_questions(header, plen, daemon->namebuff);
|
||||
#ifdef HAVE_DNSSEC
|
||||
int do_dnssec = 0;
|
||||
@@ -313,8 +322,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
forward->sentto->failed_queries++;
|
||||
if (!option_bool(OPT_ORDER))
|
||||
{
|
||||
+ sd = forward->sentto->serv_domain;
|
||||
forward->forwardall = 1;
|
||||
- daemon->last_server = NULL;
|
||||
+ if (sd)
|
||||
+ sd->last_server = NULL;
|
||||
}
|
||||
type = forward->sentto->flags & SERV_TYPE;
|
||||
#ifdef HAVE_DNSSEC
|
||||
@@ -363,10 +374,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
|
||||
return 1;
|
||||
}
|
||||
-
|
||||
+
|
||||
if (gotname)
|
||||
- flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
|
||||
-
|
||||
+ flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind, &sd);
|
||||
+
|
||||
#ifdef HAVE_DNSSEC
|
||||
do_dnssec = type & SERV_DO_DNSSEC;
|
||||
#endif
|
||||
@@ -407,18 +418,18 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
always try all the available servers,
|
||||
otherwise, use the one last known to work. */
|
||||
|
||||
- if (type == 0)
|
||||
+ if (sd)
|
||||
{
|
||||
if (option_bool(OPT_ORDER))
|
||||
start = daemon->servers;
|
||||
- else if (!(start = daemon->last_server) ||
|
||||
- daemon->forwardcount++ > FORWARD_TEST ||
|
||||
- difftime(now, daemon->forwardtime) > FORWARD_TIME)
|
||||
+ else if (!(start = sd->last_server) ||
|
||||
+ sd->forwardcount++ > FORWARD_TEST ||
|
||||
+ difftime(now, sd->forwardtime) > FORWARD_TIME)
|
||||
{
|
||||
start = daemon->servers;
|
||||
forward->forwardall = 1;
|
||||
- daemon->forwardcount = 0;
|
||||
- daemon->forwardtime = now;
|
||||
+ sd->forwardcount = 0;
|
||||
+ sd->forwardtime = now;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -758,6 +769,7 @@ void reply_query(int fd, time_t now)
|
||||
size_t nn;
|
||||
struct server *server;
|
||||
void *hash;
|
||||
+ struct server_domain *sd;
|
||||
|
||||
/* packet buffer overwritten */
|
||||
daemon->srv_save = NULL;
|
||||
@@ -845,7 +857,8 @@ void reply_query(int fd, time_t now)
|
||||
}
|
||||
|
||||
server = forward->sentto;
|
||||
- if ((forward->sentto->flags & SERV_TYPE) == 0)
|
||||
+ sd = server->serv_domain;
|
||||
+ if (sd)
|
||||
{
|
||||
if (RCODE(header) == REFUSED)
|
||||
server = NULL;
|
||||
@@ -863,7 +876,7 @@ void reply_query(int fd, time_t now)
|
||||
}
|
||||
}
|
||||
if (!option_bool(OPT_ALL_SERVERS))
|
||||
- daemon->last_server = server;
|
||||
+ sd->last_server = server;
|
||||
}
|
||||
|
||||
/* We tried resending to this server with a smaller maximum size and got an answer.
|
||||
@@ -964,7 +977,7 @@ void reply_query(int fd, time_t now)
|
||||
/* Find server to forward to. This will normally be the
|
||||
same as for the original query, but may be another if
|
||||
servers for domains are involved. */
|
||||
- if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL) == 0)
|
||||
+ if (search_servers(now, NULL, F_DNSSECOK, daemon->keyname, &type, &domain, NULL, &sd) == 0)
|
||||
{
|
||||
struct server *start = server, *new_server = NULL;
|
||||
|
||||
@@ -1541,7 +1554,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
/* Find server to forward to. This will normally be the
|
||||
same as for the original query, but may be another if
|
||||
servers for domains are involved. */
|
||||
- if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL) != 0)
|
||||
+ if (search_servers(now, NULL, F_DNSSECOK, keyname, &type, &domain, NULL, NULL) != 0)
|
||||
{
|
||||
new_status = STAT_ABANDONED;
|
||||
break;
|
||||
@@ -1814,11 +1827,12 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
int type = SERV_DO_DNSSEC;
|
||||
char *domain = NULL;
|
||||
unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
|
||||
+ struct server_domain *sd = NULL;
|
||||
|
||||
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
|
||||
|
||||
if (gotname)
|
||||
- flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
|
||||
+ flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind, &sd);
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID) && (type & SERV_DO_DNSSEC))
|
||||
@@ -1839,10 +1853,10 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
|
||||
type &= ~SERV_DO_DNSSEC;
|
||||
|
||||
- if (type != 0 || option_bool(OPT_ORDER) || !daemon->last_server)
|
||||
+ if (!sd || option_bool(OPT_ORDER) || !sd->last_server)
|
||||
last_server = daemon->servers;
|
||||
else
|
||||
- last_server = daemon->last_server;
|
||||
+ last_server = sd->last_server;
|
||||
|
||||
if (!flags && last_server)
|
||||
{
|
||||
@@ -2439,9 +2453,7 @@ void server_gone(struct server *server)
|
||||
if (daemon->randomsocks[i].refcount != 0 && daemon->randomsocks[i].serv == server)
|
||||
daemon->randomsocks[i].serv = NULL;
|
||||
|
||||
- if (daemon->last_server == server)
|
||||
- daemon->last_server = NULL;
|
||||
-
|
||||
+ /* last_server cleared by server_domain_cleanup */
|
||||
if (daemon->srv_save == server)
|
||||
daemon->srv_save = NULL;
|
||||
}
|
||||
diff --git a/src/network.c b/src/network.c
|
||||
index 4eda1fd..4d140bb 100644
|
||||
--- a/src/network.c
|
||||
+++ b/src/network.c
|
||||
@@ -1428,6 +1428,29 @@ void cleanup_servers(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
+void server_domains_cleanup(void)
|
||||
+{
|
||||
+ struct server_domain *sd, *tmp, **up;
|
||||
+
|
||||
+ /* unlink and free anything still marked. */
|
||||
+ for (up = &daemon->server_domains, sd=*up; sd; sd = tmp)
|
||||
+ {
|
||||
+ tmp = sd->next;
|
||||
+ if (sd->flags & SERV_MARK)
|
||||
+ {
|
||||
+ *up = sd->next;
|
||||
+ if (sd->domain)
|
||||
+ free(sd->domain);
|
||||
+ free(sd);
|
||||
+ }
|
||||
+ else {
|
||||
+ up = &sd->next;
|
||||
+ if (sd->last_server && (sd->last_server->flags & SERV_MARK))
|
||||
+ sd->last_server = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void add_update_server(int flags,
|
||||
union mysockaddr *addr,
|
||||
union mysockaddr *source_addr,
|
||||
@@ -1507,10 +1530,72 @@ void add_update_server(int flags,
|
||||
}
|
||||
}
|
||||
|
||||
+static const char *server_get_domain(const struct server *serv)
|
||||
+{
|
||||
+ const char *domain = serv->domain;
|
||||
+
|
||||
+ if (serv->flags & SERV_HAS_DOMAIN)
|
||||
+ /* .example.com is valid */
|
||||
+ while (*domain == '.')
|
||||
+ domain++;
|
||||
+
|
||||
+ return domain;
|
||||
+}
|
||||
+
|
||||
+struct server_domain *server_domain_find_domain(const char *domain)
|
||||
+{
|
||||
+ struct server_domain *sd;
|
||||
+ for (sd = daemon->server_domains; sd; sd = sd->next)
|
||||
+ if ((!domain && sd->domain == domain) || (domain && sd->domain && hostname_isequal(domain, sd->domain)))
|
||||
+ return sd;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**< Test structure has already set domain pointer.
|
||||
+ *
|
||||
+ * If not, create a new record. */
|
||||
+struct server_domain *server_domain_new(struct server *serv)
|
||||
+{
|
||||
+ struct server_domain *sd;
|
||||
+
|
||||
+ if ((sd = whine_malloc(sizeof(struct server_domain))))
|
||||
+ {
|
||||
+ const char *domain = server_get_domain(serv);
|
||||
+
|
||||
+ /* Ensure all serv->domain values have own record in server_domain.
|
||||
+ * Add a new record. */
|
||||
+ if (domain)
|
||||
+ {
|
||||
+ size_t len = strlen(domain)+1;
|
||||
+ sd->domain = whine_malloc(len);
|
||||
+ if (sd->domain)
|
||||
+ memcpy(sd->domain, domain, len);
|
||||
+ }
|
||||
+ sd->next = daemon->server_domains;
|
||||
+ serv->serv_domain = sd;
|
||||
+ daemon->server_domains = sd;
|
||||
+ }
|
||||
+ return sd;
|
||||
+}
|
||||
+
|
||||
+/**< Test structure has already set domain pointer.
|
||||
+ *
|
||||
+ * If not, create a new record. */
|
||||
+static void server_domain_check(struct server *serv)
|
||||
+{
|
||||
+ struct server_domain *sd = serv->serv_domain;
|
||||
+
|
||||
+ if (sd)
|
||||
+ sd->flags &= (~SERV_MARK); /* found domain, mark active */
|
||||
+ else
|
||||
+ server_domain_new(serv);
|
||||
+}
|
||||
+
|
||||
void check_servers(void)
|
||||
{
|
||||
struct irec *iface;
|
||||
struct server *serv;
|
||||
+ struct server_domain *sd;
|
||||
struct serverfd *sfd, *tmp, **up;
|
||||
int port = 0, count;
|
||||
int locals = 0;
|
||||
@@ -1522,10 +1607,14 @@ void check_servers(void)
|
||||
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
||||
sfd->used = 0;
|
||||
|
||||
+ for (sd = daemon->server_domains; sd; sd = sd->next)
|
||||
+ sd->flags |= SERV_MARK;
|
||||
+
|
||||
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
||||
{
|
||||
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||
{
|
||||
+
|
||||
/* Init edns_pktsz for newly created server records. */
|
||||
if (serv->edns_pktsz == 0)
|
||||
serv->edns_pktsz = daemon->edns_pktsz;
|
||||
@@ -1541,12 +1630,8 @@ void check_servers(void)
|
||||
if (serv->flags & SERV_HAS_DOMAIN)
|
||||
{
|
||||
struct ds_config *ds;
|
||||
- char *domain = serv->domain;
|
||||
-
|
||||
- /* .example.com is valid */
|
||||
- while (*domain == '.')
|
||||
- domain++;
|
||||
-
|
||||
+ const char *domain = server_get_domain(serv);
|
||||
+
|
||||
for (ds = daemon->ds; ds; ds = ds->next)
|
||||
if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
|
||||
break;
|
||||
@@ -1556,7 +1641,6 @@ void check_servers(void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
-
|
||||
port = prettyprint_addr(&serv->addr, daemon->namebuff);
|
||||
|
||||
/* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
|
||||
@@ -1591,6 +1675,8 @@ void check_servers(void)
|
||||
|
||||
if (serv->sfd)
|
||||
serv->sfd->used = 1;
|
||||
+
|
||||
+ server_domain_check(serv);
|
||||
}
|
||||
|
||||
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
|
||||
@@ -1653,6 +1739,7 @@ void check_servers(void)
|
||||
up = &sfd->next;
|
||||
}
|
||||
|
||||
+ server_domains_cleanup();
|
||||
cleanup_servers();
|
||||
}
|
||||
|
||||
diff --git a/src/option.c b/src/option.c
|
||||
index abc5a48..6fa7bbd 100644
|
||||
--- a/src/option.c
|
||||
+++ b/src/option.c
|
||||
@@ -906,6 +906,7 @@ static struct server *add_rev4(struct in_addr addr, int msize)
|
||||
p += sprintf(p, "in-addr.arpa");
|
||||
|
||||
serv->flags = SERV_HAS_DOMAIN;
|
||||
+ server_domain_new(serv);
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
|
||||
@@ -930,6 +931,7 @@ static struct server *add_rev6(struct in6_addr *addr, int msize)
|
||||
p += sprintf(p, "ip6.arpa");
|
||||
|
||||
serv->flags = SERV_HAS_DOMAIN;
|
||||
+ server_domain_new(serv);
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
|
||||
@@ -2231,6 +2233,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
serv->domain = d;
|
||||
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
|
||||
+ server_domain_new(serv);
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
}
|
||||
@@ -2275,6 +2278,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
serv->domain = d;
|
||||
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
|
||||
+ server_domain_new(serv);
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
}
|
||||
@@ -2525,6 +2529,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
newlist = serv;
|
||||
serv->domain = domain;
|
||||
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
|
||||
+ server_domain_new(serv);
|
||||
arg = end;
|
||||
if (rebind)
|
||||
break;
|
||||
--
|
||||
2.34.1
|
||||
|
25
SOURCES/dnsmasq-2.80-man-nameing.patch
Normal file
25
SOURCES/dnsmasq-2.80-man-nameing.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 03212e533b1e07aba30d2f4112009dc3af867ea5 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Tue, 4 Sep 2018 17:52:28 +0100
|
||||
Subject: [PATCH] Manpage typo.
|
||||
|
||||
---
|
||||
man/dnsmasq.8 | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
|
||||
index ebfadba..a62860e 100644
|
||||
--- a/man/dnsmasq.8
|
||||
+++ b/man/dnsmasq.8
|
||||
@@ -27,7 +27,7 @@ TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP. The PXE
|
||||
.PP
|
||||
The dnsmasq DHCPv6 server provides the same set of features as the
|
||||
DHCPv4 server, and in addition, it includes router advertisements and
|
||||
-a neat feature which allows nameing for clients which use DHCPv4 and
|
||||
+a neat feature which allows naming for clients which use DHCPv4 and
|
||||
stateless autoconfiguration only for IPv6 configuration. There is support for doing address allocation (both DHCPv6 and RA) from subnets which are dynamically delegated via DHCPv6 prefix delegation.
|
||||
.PP
|
||||
Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions, and allows unneeded functions to be omitted from the compiled binary.
|
||||
--
|
||||
2.31.1
|
||||
|
28
SOURCES/dnsmasq-2.80-synth-domain-RHEL-15216.patch
Normal file
28
SOURCES/dnsmasq-2.80-synth-domain-RHEL-15216.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 0a970b2a19c9fe5166e846d8a0c8b4f4fa5f1b4f Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Mon, 30 Jul 2018 14:55:39 +0100
|
||||
Subject: [PATCH] Fix crash parsing a --synth-domain with no prefix. Problem
|
||||
introduced in 2.79/6b2b564ac34cb3c862f168e6b1457f9f0b9ca69c
|
||||
|
||||
---
|
||||
src/option.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/option.c b/src/option.c
|
||||
index b22fc90..4e54afb 100644
|
||||
--- a/src/option.c
|
||||
+++ b/src/option.c
|
||||
@@ -2347,7 +2347,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
char *star;
|
||||
new->next = daemon->synth_domains;
|
||||
daemon->synth_domains = new;
|
||||
- if ((star = strrchr(new->prefix, '*')) && *(star+1) == 0)
|
||||
+ if (new->prefix &&
|
||||
+ (star = strrchr(new->prefix, '*'))
|
||||
+ && *(star+1) == 0)
|
||||
{
|
||||
*star = 0;
|
||||
new->indexed = 1;
|
||||
--
|
||||
2.41.0
|
||||
|
56
SOURCES/dnsmasq-2.81-dhcpv6-relay-link-address.patch
Normal file
56
SOURCES/dnsmasq-2.81-dhcpv6-relay-link-address.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From f8c77edbdffb8ada7753ea9fa104f0f6da70cfe3 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Thu, 10 Jan 2019 21:58:18 +0000
|
||||
Subject: [PATCH] Fix removal of DHCP_CLIENT_MAC options from DHCPv6 relay
|
||||
replies.
|
||||
|
||||
---
|
||||
src/rfc3315.c | 30 +++++++++++++++++-------------
|
||||
1 file changed, 17 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c
|
||||
index d3c1722..79b2a86 100644
|
||||
--- a/src/rfc3315.c
|
||||
+++ b/src/rfc3315.c
|
||||
@@ -219,21 +219,25 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
if (opt6_ptr(opt, 0) + opt6_len(opt) > end)
|
||||
return 0;
|
||||
|
||||
- int o = new_opt6(opt6_type(opt));
|
||||
- if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
||||
+ /* Don't copy MAC address into reply. */
|
||||
+ if (opt6_type(opt) != OPTION6_CLIENT_MAC)
|
||||
{
|
||||
- struct in6_addr align;
|
||||
- /* the packet data is unaligned, copy to aligned storage */
|
||||
- memcpy(&align, inbuff + 2, IN6ADDRSZ);
|
||||
- state->link_address = &align;
|
||||
- /* zero is_unicast since that is now known to refer to the
|
||||
- relayed packet, not the original sent by the client */
|
||||
- if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
|
||||
- return 0;
|
||||
+ int o = new_opt6(opt6_type(opt));
|
||||
+ if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
||||
+ {
|
||||
+ struct in6_addr align;
|
||||
+ /* the packet data is unaligned, copy to aligned storage */
|
||||
+ memcpy(&align, inbuff + 2, IN6ADDRSZ);
|
||||
+ state->link_address = &align;
|
||||
+ /* zero is_unicast since that is now known to refer to the
|
||||
+ relayed packet, not the original sent by the client */
|
||||
+ if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
|
||||
+ return 0;
|
||||
+ }
|
||||
+ else
|
||||
+ put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
||||
+ end_opt6(o);
|
||||
}
|
||||
- else if (opt6_type(opt) != OPTION6_CLIENT_MAC)
|
||||
- put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
||||
- end_opt6(o);
|
||||
}
|
||||
|
||||
return 1;
|
||||
--
|
||||
2.39.1
|
||||
|
25
SOURCES/dnsmasq-2.81-linux-SIOCGSTAMP.patch
Normal file
25
SOURCES/dnsmasq-2.81-linux-SIOCGSTAMP.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 3052ce208acf602f0163166dcefb7330d537cedb Mon Sep 17 00:00:00 2001
|
||||
From: Jiri Slaby <jslaby@suse.cz>
|
||||
Date: Wed, 24 Jul 2019 17:34:48 +0100
|
||||
Subject: [PATCH] Fix build after y2038 changes in glib.
|
||||
|
||||
SIOCGSTAMP is defined in linux/sockios.h, not asm/sockios.h now.
|
||||
---
|
||||
src/dnsmasq.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index ff3204a..3ef04ad 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -137,6 +137,7 @@ typedef unsigned long long u64;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
+#include <linux/sockios.h>
|
||||
#include <linux/capability.h>
|
||||
/* There doesn't seem to be a universally-available
|
||||
userspace header for these. */
|
||||
--
|
||||
2.36.1
|
||||
|
45
SOURCES/dnsmasq-2.81-netlink-table.patch
Normal file
45
SOURCES/dnsmasq-2.81-netlink-table.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 595b2e2e87f152c4ade7e2d66cb78915096f60c2 Mon Sep 17 00:00:00 2001
|
||||
From: Donald Sharp <donaldsharp72@gmail.com>
|
||||
Date: Mon, 2 Mar 2020 11:23:36 -0500
|
||||
Subject: [PATCH] Ignore routes in non-main tables
|
||||
|
||||
Route lookup in Linux is bounded by `ip rules` as well
|
||||
as the contents of specific routing tables. With the
|
||||
advent of vrf's(l3mdev's) non-default tables are regularly being
|
||||
used for routing purposes.
|
||||
|
||||
dnsmasq listens to all route changes on the box and responds
|
||||
to each one with an event. This is *expensive* when a full
|
||||
BGP routing table is placed into the linux kernel, moreso
|
||||
when dnsmasq is responding to events in tables that it will
|
||||
never actually need to respond to, since dnsmasq at this
|
||||
point in time has no concept of vrf's and would need
|
||||
to be programmed to understand them. Help alleviate this load
|
||||
by reducing the set of data that dnsmasq pays attention to
|
||||
when we know there are events that are not useful at this
|
||||
point in time.
|
||||
|
||||
Signed-off-by: Donald Sharp <donaldsharp72@gmail.com>
|
||||
(cherry picked from commit b2ed691eb3ca6488a8878f5f3dd950a07b14a9db)
|
||||
---
|
||||
src/netlink.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/netlink.c b/src/netlink.c
|
||||
index 8cd51af..0a3da3e 100644
|
||||
--- a/src/netlink.c
|
||||
+++ b/src/netlink.c
|
||||
@@ -363,7 +363,9 @@ static void nl_async(struct nlmsghdr *h)
|
||||
failing. */
|
||||
struct rtmsg *rtm = NLMSG_DATA(h);
|
||||
|
||||
- if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK)
|
||||
+ if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK &&
|
||||
+ (rtm->rtm_table == RT_TABLE_MAIN ||
|
||||
+ rtm->rtm_table == RT_TABLE_LOCAL))
|
||||
queue_event(EVENT_NEWROUTE);
|
||||
}
|
||||
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||
--
|
||||
2.26.2
|
||||
|
132
SOURCES/dnsmasq-2.81-optimize-fds-close.patch
Normal file
132
SOURCES/dnsmasq-2.81-optimize-fds-close.patch
Normal 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)
|
||||
{
|
161
SOURCES/dnsmasq-2.81-option6-ntp-server-suboption.patch
Normal file
161
SOURCES/dnsmasq-2.81-option6-ntp-server-suboption.patch
Normal file
@ -0,0 +1,161 @@
|
||||
From 03936d309782da038a2982b08fce7be85d884f0e Mon Sep 17 00:00:00 2001
|
||||
From: Vladislav Grishenko <themiron@mail.ru>
|
||||
Date: Sun, 8 Mar 2020 15:34:34 +0000
|
||||
Subject: [PATCH] Add DHCPv6 ntp-server (56) option handling.
|
||||
|
||||
There was discussion in the past regarding DHCPv6 NTP server option
|
||||
which needs special subclassing per RFC5908.
|
||||
|
||||
Patch adds support for unicast, multicast IPv6 address and for FQDN string,
|
||||
preserving possibly used (as suggested earlier) hex value.
|
||||
|
||||
Unfortunately it's still not fully free from limitations - only address list or
|
||||
only fqdn value list is possible, not mixed due current
|
||||
state option parsing & flagging.
|
||||
|
||||
(cherry picked from commit dded78b2338147daf69064d6d48c16b12744e441)
|
||||
---
|
||||
src/dhcp-common.c | 2 +-
|
||||
src/dhcp6-protocol.h | 4 ++++
|
||||
src/option.c | 19 ++++++++++++++++---
|
||||
src/rfc3315.c | 24 ++++++++++++++++++++----
|
||||
4 files changed, 41 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
|
||||
index 368d686..242a5a1 100644
|
||||
--- a/src/dhcp-common.c
|
||||
+++ b/src/dhcp-common.c
|
||||
@@ -642,7 +642,7 @@ static const struct opttab_t opttab6[] = {
|
||||
{ "sntp-server", 31, OT_ADDR_LIST },
|
||||
{ "information-refresh-time", 32, OT_TIME },
|
||||
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
||||
- { "ntp-server", 56, 0 },
|
||||
+ { "ntp-server", 56, 0 /* OT_ADDR_LIST | OT_RFC1035_NAME */ },
|
||||
{ "bootfile-url", 59, OT_NAME },
|
||||
{ "bootfile-param", 60, OT_CSTRING },
|
||||
{ "client-arch", 61, 2 | OT_DEC }, /* RFC 5970 */
|
||||
diff --git a/src/dhcp6-protocol.h b/src/dhcp6-protocol.h
|
||||
index fee5d28..05560e8 100644
|
||||
--- a/src/dhcp6-protocol.h
|
||||
+++ b/src/dhcp6-protocol.h
|
||||
@@ -59,12 +59,16 @@
|
||||
#define OPTION6_REMOTE_ID 37
|
||||
#define OPTION6_SUBSCRIBER_ID 38
|
||||
#define OPTION6_FQDN 39
|
||||
+#define OPTION6_NTP_SERVER 56
|
||||
#define OPTION6_CLIENT_MAC 79
|
||||
|
||||
/* replace this with the real number when allocated.
|
||||
defining this also enables the relevant code. */
|
||||
/* #define OPTION6_PREFIX_CLASS 99 */
|
||||
|
||||
+#define NTP_SUBOPTION_SRV_ADDR 1
|
||||
+#define NTP_SUBOPTION_MC_ADDR 2
|
||||
+#define NTP_SUBOPTION_SRV_FQDN 3
|
||||
|
||||
#define DHCP6SUCCESS 0
|
||||
#define DHCP6UNSPEC 1
|
||||
diff --git a/src/option.c b/src/option.c
|
||||
index 6fa7bbd..1382c55 100644
|
||||
--- a/src/option.c
|
||||
+++ b/src/option.c
|
||||
@@ -1245,6 +1245,12 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
if (!found_dig)
|
||||
is_dec = is_addr = 0;
|
||||
|
||||
+#ifdef HAVE_DHCP6
|
||||
+ /* NTP server option takes hex, addresses or FQDN */
|
||||
+ if (is6 && new->opt == OPTION6_NTP_SERVER && !is_hex)
|
||||
+ opt_len |= is_addr6 ? OT_ADDR_LIST : OT_RFC1035_NAME;
|
||||
+#endif
|
||||
+
|
||||
/* We know that some options take addresses */
|
||||
if (opt_len & OT_ADDR_LIST)
|
||||
{
|
||||
@@ -1505,8 +1511,9 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
}
|
||||
else if (comma && (opt_len & OT_RFC1035_NAME))
|
||||
{
|
||||
- unsigned char *p = NULL, *newp, *end;
|
||||
+ unsigned char *p = NULL, *q, *newp, *end;
|
||||
int len = 0;
|
||||
+ int header_size = (is6 && new->opt == OPTION6_NTP_SERVER) ? 4 : 0;
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
|
||||
@@ -1516,7 +1523,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
if (!dom)
|
||||
goto_err(_("bad domain in dhcp-option"));
|
||||
|
||||
- newp = opt_malloc(len + strlen(dom) + 2);
|
||||
+ newp = opt_malloc(len + header_size + strlen(dom) + 2);
|
||||
|
||||
if (p)
|
||||
{
|
||||
@@ -1525,8 +1532,14 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
}
|
||||
|
||||
p = newp;
|
||||
- end = do_rfc1035_name(p + len, dom, NULL);
|
||||
+ q = p + len;
|
||||
+ end = do_rfc1035_name(q + header_size, dom, NULL);
|
||||
*end++ = 0;
|
||||
+ if (is6 && new->opt == OPTION6_NTP_SERVER)
|
||||
+ {
|
||||
+ PUTSHORT(NTP_SUBOPTION_SRV_FQDN, q);
|
||||
+ PUTSHORT(end - q - 2, q);
|
||||
+ }
|
||||
len = end - p;
|
||||
free(dom);
|
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c
|
||||
index 1f1aad8..0fa12ad 100644
|
||||
--- a/src/rfc3315.c
|
||||
+++ b/src/rfc3315.c
|
||||
@@ -1380,23 +1380,39 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
||||
|
||||
for (a = (struct in6_addr *)opt_cfg->val, j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
|
||||
{
|
||||
+ struct in6_addr *p = NULL;
|
||||
+
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(a))
|
||||
{
|
||||
if (!add_local_addrs(state->context))
|
||||
- put_opt6(state->fallback, IN6ADDRSZ);
|
||||
+ p = state->fallback;
|
||||
}
|
||||
else if (IN6_IS_ADDR_ULA_ZERO(a))
|
||||
{
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(state->ula_addr))
|
||||
- put_opt6(state->ula_addr, IN6ADDRSZ);
|
||||
+ p = state->ula_addr;
|
||||
}
|
||||
else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
|
||||
{
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(state->ll_addr))
|
||||
- put_opt6(state->ll_addr, IN6ADDRSZ);
|
||||
+ p = state->ll_addr;
|
||||
+ }
|
||||
+ else
|
||||
+ p = a;
|
||||
+
|
||||
+ if (!p)
|
||||
+ continue;
|
||||
+ else if (opt_cfg->opt == OPTION6_NTP_SERVER)
|
||||
+ {
|
||||
+ if (IN6_IS_ADDR_MULTICAST(p))
|
||||
+ o1 = new_opt6(NTP_SUBOPTION_MC_ADDR);
|
||||
+ else
|
||||
+ o1 = new_opt6(NTP_SUBOPTION_SRV_ADDR);
|
||||
+ put_opt6(p, IN6ADDRSZ);
|
||||
+ end_opt6(o1);
|
||||
}
|
||||
else
|
||||
- put_opt6(a, IN6ADDRSZ);
|
||||
+ put_opt6(p, IN6ADDRSZ);
|
||||
}
|
||||
|
||||
end_opt6(o);
|
||||
--
|
||||
2.36.1
|
||||
|
62
SOURCES/dnsmasq-2.81-rh1829448.patch
Normal file
62
SOURCES/dnsmasq-2.81-rh1829448.patch
Normal 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
|
237
SOURCES/dnsmasq-2.84-bind-dynamic-netlink.patch
Normal file
237
SOURCES/dnsmasq-2.84-bind-dynamic-netlink.patch
Normal file
@ -0,0 +1,237 @@
|
||||
From 5010c42c47b7b5a3d68d83369d6c17ed0bc11cff Mon Sep 17 00:00:00 2001
|
||||
From: Petr Mensik <pemensik@redhat.com>
|
||||
Date: Wed, 17 Feb 2021 11:47:28 +0100
|
||||
Subject: [PATCH] Correct occasional --bind-dynamic synchronization break
|
||||
|
||||
Request only one re-read of addresses and/or routes
|
||||
|
||||
Previous implementation re-reads systemd addresses exactly the same
|
||||
number of time equal number of notifications received.
|
||||
This is not necessary, we need just notification of change, then re-read
|
||||
the current state and adapt listeners. Repeated re-reading slows netlink
|
||||
processing and highers CPU usage on mass interface changes.
|
||||
|
||||
Continue reading multicast events from netlink, even when ENOBUFS
|
||||
arrive. Broadcasts are not trusted anyway and refresh would be done in
|
||||
iface_enumerate. Save queued events sent again.
|
||||
|
||||
Remove sleeping on netlink ENOBUFS
|
||||
|
||||
With reduced number of written events netlink should receive ENOBUFS
|
||||
rarely. It does not make sense to wait if it is received. It is just a
|
||||
signal some packets got missing. Fast reading all pending packets is required,
|
||||
seq checking ensures it already. Finishes changes by
|
||||
commit 1d07667ac77c55b9de56b1b2c385167e0e0ec27a.
|
||||
|
||||
Move restart from iface_enumerate to enumerate_interfaces
|
||||
|
||||
When ENOBUFS is received, restart of reading addresses is done. But
|
||||
previously found addresses might not have been found this time. In order
|
||||
to catch this, restart both IPv4 and IPv6 enumeration with clearing
|
||||
found interfaces first. It should deliver up-to-date state also after
|
||||
ENOBUFS.
|
||||
|
||||
Read all netlink messages before netlink restart
|
||||
|
||||
Before writing again into netlink socket, try fetching all pending
|
||||
messages. They would be ignored, only might trigger new address
|
||||
synchronization. Should ensure new try has better chance to succeed.
|
||||
|
||||
Request sending ENOBUFS again
|
||||
|
||||
ENOBUFS error handling was improved. Netlink is correctly drained before
|
||||
sending a new request again. It seems ENOBUFS supression is no longer
|
||||
necessary or wanted. Let kernel tell us when it failed and handle it a
|
||||
good way.
|
||||
---
|
||||
src/netlink.c | 67 ++++++++++++++++++++++++++++++++++++---------------
|
||||
src/network.c | 11 +++++++--
|
||||
2 files changed, 57 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/netlink.c b/src/netlink.c
|
||||
index ac1a1c5..f95f3e8 100644
|
||||
--- a/src/netlink.c
|
||||
+++ b/src/netlink.c
|
||||
@@ -32,13 +32,21 @@
|
||||
|
||||
#ifndef NDA_RTA
|
||||
# define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
|
||||
-#endif
|
||||
+#endif
|
||||
+
|
||||
+/* Used to request refresh of addresses or routes just once,
|
||||
+ * when multiple changes might be announced. */
|
||||
+enum async_states {
|
||||
+ STATE_NEWADDR = (1 << 0),
|
||||
+ STATE_NEWROUTE = (1 << 1),
|
||||
+};
|
||||
|
||||
|
||||
static struct iovec iov;
|
||||
static u32 netlink_pid;
|
||||
|
||||
-static void nl_async(struct nlmsghdr *h);
|
||||
+static unsigned nl_async(struct nlmsghdr *h, unsigned state);
|
||||
+static void nl_multicast_state(unsigned state);
|
||||
|
||||
void netlink_init(void)
|
||||
{
|
||||
@@ -135,7 +143,9 @@ static ssize_t netlink_recv(void)
|
||||
|
||||
|
||||
/* family = AF_UNSPEC finds ARP table entries.
|
||||
- family = AF_LOCAL finds MAC addresses. */
|
||||
+ family = AF_LOCAL finds MAC addresses.
|
||||
+ returns 0 on failure, 1 on success, -1 when restart is required
|
||||
+*/
|
||||
int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
{
|
||||
struct sockaddr_nl addr;
|
||||
@@ -143,6 +153,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
ssize_t len;
|
||||
static unsigned int seq = 0;
|
||||
int callback_ok = 1;
|
||||
+ unsigned state = 0;
|
||||
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
@@ -154,7 +165,6 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
addr.nl_groups = 0;
|
||||
addr.nl_pid = 0; /* address to kernel */
|
||||
|
||||
- again:
|
||||
if (family == AF_UNSPEC)
|
||||
req.nlh.nlmsg_type = RTM_GETNEIGH;
|
||||
else if (family == AF_LOCAL)
|
||||
@@ -181,8 +191,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
{
|
||||
if (errno == ENOBUFS)
|
||||
{
|
||||
- sleep(1);
|
||||
- goto again;
|
||||
+ nl_multicast_state(state);
|
||||
+ return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -191,7 +201,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
if (h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
/* May be multicast arriving async */
|
||||
- nl_async(h);
|
||||
+ state = nl_async(h, state);
|
||||
}
|
||||
else if (h->nlmsg_seq != seq)
|
||||
{
|
||||
@@ -327,26 +337,36 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
}
|
||||
}
|
||||
|
||||
-void netlink_multicast(void)
|
||||
+static void nl_multicast_state(unsigned state)
|
||||
{
|
||||
ssize_t len;
|
||||
struct nlmsghdr *h;
|
||||
int flags;
|
||||
-
|
||||
- /* don't risk blocking reading netlink messages here. */
|
||||
+
|
||||
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
|
||||
fcntl(daemon->netlinkfd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
return;
|
||||
+
|
||||
+ do {
|
||||
+ /* don't risk blocking reading netlink messages here. */
|
||||
+ while ((len = netlink_recv()) != -1)
|
||||
|
||||
- if ((len = netlink_recv()) != -1)
|
||||
- for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||
- nl_async(h);
|
||||
-
|
||||
+ for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||
+ state = nl_async(h, state);
|
||||
+ } while (errno == ENOBUFS);
|
||||
+
|
||||
/* restore non-blocking status */
|
||||
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
||||
}
|
||||
|
||||
-static void nl_async(struct nlmsghdr *h)
|
||||
+void netlink_multicast(void)
|
||||
+{
|
||||
+ unsigned state = 0;
|
||||
+ nl_multicast_state(state);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static unsigned nl_async(struct nlmsghdr *h, unsigned state)
|
||||
{
|
||||
if (h->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
@@ -354,7 +374,8 @@ static void nl_async(struct nlmsghdr *h)
|
||||
if (err->error != 0)
|
||||
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
||||
}
|
||||
- else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
||||
+ else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE &&
|
||||
+ (state & STATE_NEWROUTE)==0)
|
||||
{
|
||||
/* We arrange to receive netlink multicast messages whenever the network route is added.
|
||||
If this happens and we still have a DNS packet in the buffer, we re-send it.
|
||||
@@ -366,10 +387,18 @@ static void nl_async(struct nlmsghdr *h)
|
||||
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK &&
|
||||
(rtm->rtm_table == RT_TABLE_MAIN ||
|
||||
rtm->rtm_table == RT_TABLE_LOCAL))
|
||||
- queue_event(EVENT_NEWROUTE);
|
||||
+ {
|
||||
+ queue_event(EVENT_NEWROUTE);
|
||||
+ state |= STATE_NEWROUTE;
|
||||
+ }
|
||||
+ }
|
||||
+ else if ((h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR) &&
|
||||
+ (state & STATE_NEWADDR)==0)
|
||||
+ {
|
||||
+ queue_event(EVENT_NEWADDR);
|
||||
+ state |= STATE_NEWADDR;
|
||||
}
|
||||
- else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||
- queue_event(EVENT_NEWADDR);
|
||||
+ return state;
|
||||
}
|
||||
#endif
|
||||
|
||||
diff --git a/src/network.c b/src/network.c
|
||||
index c6e7d89..47caf38 100644
|
||||
--- a/src/network.c
|
||||
+++ b/src/network.c
|
||||
@@ -656,7 +656,8 @@ int enumerate_interfaces(int reset)
|
||||
|
||||
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
return 0;
|
||||
-
|
||||
+
|
||||
+again:
|
||||
/* Mark interfaces for garbage collection */
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
iface->found = 0;
|
||||
@@ -709,10 +710,16 @@ int enumerate_interfaces(int reset)
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6);
|
||||
+ if (ret < 0)
|
||||
+ goto again;
|
||||
#endif
|
||||
|
||||
if (ret)
|
||||
- ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4);
|
||||
+ {
|
||||
+ ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4);
|
||||
+ if (ret < 0)
|
||||
+ goto again;
|
||||
+ }
|
||||
|
||||
errsave = errno;
|
||||
close(param.fd);
|
||||
--
|
||||
2.26.2
|
||||
|
1056
SOURCES/dnsmasq-2.85-CVE-2021-3448.patch
Normal file
1056
SOURCES/dnsmasq-2.85-CVE-2021-3448.patch
Normal file
File diff suppressed because it is too large
Load Diff
106
SOURCES/dnsmasq-2.85-domain-blocklist-speedup.patch
Normal file
106
SOURCES/dnsmasq-2.85-domain-blocklist-speedup.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From 4cab3d930f9236408b838adfdaaeb6508a928bbf Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Fri, 9 Jun 2023 22:11:01 +0200
|
||||
Subject: [PATCH] Use serv_domain only for regular servers
|
||||
|
||||
Do not try to use it for --local=/x/ or --address=/x/#. Some users use
|
||||
quite long list of blocks, which slows down walking trough domain list
|
||||
considerably. But searching by server_domain_find_domain is needed only
|
||||
for normal servers, which may store there last used server and number
|
||||
of recent forwarded queries. Local addresses overrides store there no
|
||||
useful information, avoid searching and adding new domains for such
|
||||
records.
|
||||
|
||||
Would also speed up searching servers when blocklists are used, because
|
||||
only domains of servers are tested.
|
||||
|
||||
Resolves: rhbz#2209031
|
||||
---
|
||||
src/forward.c | 4 ++--
|
||||
src/option.c | 13 ++++++++-----
|
||||
2 files changed, 10 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index d8e845a..989fb61 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -234,8 +234,8 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
*type = 0; /* use normal servers for this domain */
|
||||
*domain = NULL;
|
||||
}
|
||||
- if (serv_domain && !*serv_domain)
|
||||
- *serv_domain = server_domain_find_domain(*domain);
|
||||
+ if (serv_domain && !*serv_domain && (*type & SERV_HAS_DOMAIN)==0)
|
||||
+ *serv_domain = server_domain_find_domain(NULL);
|
||||
return flags;
|
||||
}
|
||||
|
||||
diff --git a/src/option.c b/src/option.c
|
||||
index 1382c55..b22fc90 100644
|
||||
--- a/src/option.c
|
||||
+++ b/src/option.c
|
||||
@@ -906,7 +906,7 @@ static struct server *add_rev4(struct in_addr addr, int msize)
|
||||
p += sprintf(p, "in-addr.arpa");
|
||||
|
||||
serv->flags = SERV_HAS_DOMAIN;
|
||||
- server_domain_new(serv);
|
||||
+ serv->serv_domain = NULL;
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
|
||||
@@ -931,7 +931,7 @@ static struct server *add_rev6(struct in6_addr *addr, int msize)
|
||||
p += sprintf(p, "ip6.arpa");
|
||||
|
||||
serv->flags = SERV_HAS_DOMAIN;
|
||||
- server_domain_new(serv);
|
||||
+ serv->serv_domain = NULL;
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
|
||||
@@ -2246,7 +2246,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
serv->domain = d;
|
||||
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
|
||||
- server_domain_new(serv);
|
||||
+ serv->serv_domain = NULL;
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
}
|
||||
@@ -2291,7 +2291,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
serv->domain = d;
|
||||
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
|
||||
- server_domain_new(serv);
|
||||
+ serv->serv_domain = NULL;
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
}
|
||||
@@ -2542,7 +2542,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
newlist = serv;
|
||||
serv->domain = domain;
|
||||
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
|
||||
- server_domain_new(serv);
|
||||
+ serv->serv_domain = NULL;
|
||||
arg = end;
|
||||
if (rebind)
|
||||
break;
|
||||
@@ -2594,6 +2594,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
server_list_free(newlist);
|
||||
ret_err(err);
|
||||
}
|
||||
+ if ((newlist->flags & SERV_LITERAL_ADDRESS)==0)
|
||||
+ server_domain_new(newlist);
|
||||
}
|
||||
|
||||
serv = newlist;
|
||||
@@ -2637,6 +2639,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
else
|
||||
ret_err(gen_err);
|
||||
|
||||
+ server_domain_new(serv);
|
||||
string = parse_server(comma, &serv->addr, &serv->source_addr, serv->interface, &serv->flags);
|
||||
|
||||
if (string)
|
||||
--
|
||||
2.41.0
|
||||
|
83
SOURCES/dnsmasq-2.85-serv_domain-rh2186481-2.patch
Normal file
83
SOURCES/dnsmasq-2.85-serv_domain-rh2186481-2.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From 312e9f812a6b2f5ca2c2db866ffed3a0b289b945 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Wed, 10 May 2023 12:57:17 +0200
|
||||
Subject: [PATCH] fixup! Correct releasing of serv_domain
|
||||
|
||||
---
|
||||
src/dnsmasq.h | 2 +-
|
||||
src/network.c | 20 +++++++++++---------
|
||||
2 files changed, 12 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index e8a1320..711ffd3 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -1331,7 +1331,7 @@ int label_exception(int index, int family, struct all_addr *addr);
|
||||
int fix_fd(int fd);
|
||||
int tcp_interface(int fd, int af);
|
||||
struct server_domain *server_domain_find_domain(const char *domain);
|
||||
-struct server_domain *server_domain_new(struct server *serv);
|
||||
+void server_domain_new(struct server *serv);
|
||||
#ifdef HAVE_IPV6
|
||||
int set_ipv6pktinfo(int fd);
|
||||
#endif
|
||||
diff --git a/src/network.c b/src/network.c
|
||||
index b8d77fe..6faaad4 100644
|
||||
--- a/src/network.c
|
||||
+++ b/src/network.c
|
||||
@@ -1544,6 +1544,7 @@ void add_update_server(int flags,
|
||||
serv->addr = *addr;
|
||||
if (source_addr)
|
||||
serv->source_addr = *source_addr;
|
||||
+ server_domain_new(serv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1571,14 +1572,20 @@ struct server_domain *server_domain_find_domain(const char *domain)
|
||||
/**< Test structure has already set domain pointer.
|
||||
*
|
||||
* If not, create a new record. */
|
||||
-struct server_domain *server_domain_new(struct server *serv)
|
||||
+void server_domain_new(struct server *serv)
|
||||
{
|
||||
struct server_domain *sd;
|
||||
+ const char *domain = server_get_domain(serv);
|
||||
|
||||
- if ((sd = whine_malloc(sizeof(struct server_domain))))
|
||||
+ sd = server_domain_find_domain(domain);
|
||||
+ if (sd)
|
||||
{
|
||||
- const char *domain = server_get_domain(serv);
|
||||
+ serv->serv_domain = sd;
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
+ if ((sd = whine_malloc(sizeof(struct server_domain))))
|
||||
+ {
|
||||
/* Ensure all serv->domain values have own record in server_domain.
|
||||
* Add a new record. */
|
||||
if (domain)
|
||||
@@ -1592,7 +1599,6 @@ struct server_domain *server_domain_new(struct server *serv)
|
||||
serv->serv_domain = sd;
|
||||
daemon->server_domains = sd;
|
||||
}
|
||||
- return sd;
|
||||
}
|
||||
|
||||
/**< Test structure has already set domain pointer.
|
||||
@@ -1605,11 +1611,7 @@ static void server_domain_check(struct server *serv)
|
||||
if (sd)
|
||||
sd->flags &= (~SERV_MARK); /* found domain, mark active */
|
||||
else
|
||||
- {
|
||||
- sd = server_domain_find_domain(serv->domain);
|
||||
- if (!sd)
|
||||
- server_domain_new(serv);
|
||||
- }
|
||||
+ server_domain_new(serv);
|
||||
}
|
||||
|
||||
void check_servers(void)
|
||||
--
|
||||
2.40.1
|
||||
|
108
SOURCES/dnsmasq-2.85-serv_domain-rh2186481.patch
Normal file
108
SOURCES/dnsmasq-2.85-serv_domain-rh2186481.patch
Normal file
@ -0,0 +1,108 @@
|
||||
From c0e0202736f55195104dad9fec98c20d0d15df21 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Fri, 21 Apr 2023 17:04:53 +0200
|
||||
Subject: [PATCH] Correct releasing of serv_domain
|
||||
|
||||
In case the server->serv_domain points to domain also when it is not the
|
||||
last server used, ensure the reference to last_server is always reset.
|
||||
Some records might reference the server_domain, but cannot ever become
|
||||
last_server. Such as server=/example.com/#
|
||||
|
||||
Correct detection of used server_domains for standard resolvers case.
|
||||
Mark domain used even in that case, so it is not freed during
|
||||
resolv.conf reading or other nameservers change.
|
||||
---
|
||||
src/network.c | 40 +++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 31 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/network.c b/src/network.c
|
||||
index cf2f2e2..8152cac 100644
|
||||
--- a/src/network.c
|
||||
+++ b/src/network.c
|
||||
@@ -1511,7 +1511,18 @@ void mark_servers(int flag)
|
||||
}
|
||||
}
|
||||
|
||||
-static void server_domains_cleanup(void)
|
||||
+static void server_domains_pre_cleanup(void)
|
||||
+{
|
||||
+ struct server_domain *sd;
|
||||
+
|
||||
+ /* reset removed last_server. */
|
||||
+ for (sd = daemon->server_domains; sd; sd = sd->next)
|
||||
+ if ((sd->flags & SERV_MARK) == 0 && sd->last_server &&
|
||||
+ (sd->last_server->flags & SERV_MARK) != 0)
|
||||
+ sd->last_server = NULL;
|
||||
+}
|
||||
+
|
||||
+static void server_domains_post_cleanup(void)
|
||||
{
|
||||
struct server_domain *sd, *tmp, **up;
|
||||
|
||||
@@ -1528,8 +1539,6 @@ static void server_domains_cleanup(void)
|
||||
}
|
||||
else {
|
||||
up = &sd->next;
|
||||
- if (sd->last_server && (sd->last_server->flags & SERV_MARK))
|
||||
- sd->last_server = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1538,7 +1547,7 @@ void cleanup_servers(void)
|
||||
{
|
||||
struct server *serv, *tmp, **up;
|
||||
|
||||
- server_domains_cleanup();
|
||||
+ server_domains_pre_cleanup();
|
||||
|
||||
/* unlink and free anything still marked. */
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
@@ -1552,10 +1561,16 @@ void cleanup_servers(void)
|
||||
free(serv->domain);
|
||||
free(serv);
|
||||
}
|
||||
- else
|
||||
- up = &serv->next;
|
||||
+ else
|
||||
+ {
|
||||
+ up = &serv->next;
|
||||
+ if (serv->serv_domain && (serv->serv_domain->flags & SERV_MARK) != 0)
|
||||
+ serv->serv_domain = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ server_domains_post_cleanup();
|
||||
+
|
||||
#ifdef HAVE_LOOP
|
||||
/* Now we have a new set of servers, test for loops. */
|
||||
loop_send_probes();
|
||||
@@ -1699,7 +1714,11 @@ static void server_domain_check(struct server *serv)
|
||||
if (sd)
|
||||
sd->flags &= (~SERV_MARK); /* found domain, mark active */
|
||||
else
|
||||
- server_domain_new(serv);
|
||||
+ {
|
||||
+ sd = server_domain_find_domain(serv->domain);
|
||||
+ if (!sd)
|
||||
+ server_domain_new(serv);
|
||||
+ }
|
||||
}
|
||||
|
||||
void check_servers(void)
|
||||
@@ -1808,8 +1827,11 @@ void check_servers(void)
|
||||
else if (strlen(serv->domain) == 0)
|
||||
s1 = _("default"), s2 = "";
|
||||
else
|
||||
- s1 = _("domain"), s2 = serv->domain;
|
||||
-
|
||||
+ {
|
||||
+ s1 = _("domain"), s2 = serv->domain;
|
||||
+ server_domain_check(serv);
|
||||
+ }
|
||||
+
|
||||
if (serv->flags & SERV_NO_ADDR)
|
||||
{
|
||||
count--;
|
||||
--
|
||||
2.39.2
|
||||
|
28
SOURCES/dnsmasq-2.86-dhcpv6-client-arch.patch
Normal file
28
SOURCES/dnsmasq-2.86-dhcpv6-client-arch.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 9e2b6474f2074511c3911b2f777e8e8704782670 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Wed, 22 Sep 2021 14:54:01 +0200
|
||||
Subject: [PATCH] Add support for option6 names of RFC 5970
|
||||
|
||||
Client Network Interface Identifier and Client System Architecture Type
|
||||
options were not understood by dnsmasq. Add it to supported option
|
||||
types.
|
||||
---
|
||||
src/dhcp-common.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
|
||||
index 224c4d6..368d686 100644
|
||||
--- a/src/dhcp-common.c
|
||||
+++ b/src/dhcp-common.c
|
||||
@@ -645,6 +645,8 @@ static const struct opttab_t opttab6[] = {
|
||||
{ "ntp-server", 56, 0 },
|
||||
{ "bootfile-url", 59, OT_NAME },
|
||||
{ "bootfile-param", 60, OT_CSTRING },
|
||||
+ { "client-arch", 61, 2 | OT_DEC }, /* RFC 5970 */
|
||||
+ { "client-interface-id", 62, 1 | OT_DEC }, /* RFC 5970 */
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
#endif
|
||||
--
|
||||
2.31.1
|
||||
|
172
SOURCES/dnsmasq-2.87-CVE-2022-0934.patch
Normal file
172
SOURCES/dnsmasq-2.87-CVE-2022-0934.patch
Normal file
@ -0,0 +1,172 @@
|
||||
From 471cd540e755d2a5e92b4e8cd2ab2027beaba449 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Thu, 31 Mar 2022 21:35:20 +0100
|
||||
Subject: [PATCH] Fix write-after-free error in DHCPv6 code. CVE-2022-0934
|
||||
refers.
|
||||
|
||||
---
|
||||
src/rfc3315.c | 48 +++++++++++++++++++++++++++---------------------
|
||||
1 file changed, 27 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/rfc3315.c b/src/rfc3315.c
|
||||
index 554b1fe..bc77fbf 100644
|
||||
--- a/src/rfc3315.c
|
||||
+++ b/src/rfc3315.c
|
||||
@@ -36,9 +36,9 @@ struct state {
|
||||
#endif
|
||||
};
|
||||
|
||||
-static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
+static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz,
|
||||
struct in6_addr *client_addr, int is_unicast, time_t now);
|
||||
-static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now);
|
||||
+static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now);
|
||||
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
|
||||
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||
@@ -110,12 +110,12 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
|
||||
}
|
||||
|
||||
/* This cost me blood to write, it will probably cost you blood to understand - srk. */
|
||||
-static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
+static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz,
|
||||
struct in6_addr *client_addr, int is_unicast, time_t now)
|
||||
{
|
||||
void *end = inbuff + sz;
|
||||
void *opts = inbuff + 34;
|
||||
- int msg_type = *((unsigned char *)inbuff);
|
||||
+ int msg_type = *inbuff;
|
||||
unsigned char *outmsgtypep;
|
||||
void *opt;
|
||||
struct dhcp_vendor *vendor;
|
||||
@@ -241,15 +241,15 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now)
|
||||
+static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now)
|
||||
{
|
||||
void *opt;
|
||||
- int i, o, o1, start_opts;
|
||||
+ int i, o, o1, start_opts, start_msg;
|
||||
struct dhcp_opt *opt_cfg;
|
||||
struct dhcp_netid *tagif;
|
||||
struct dhcp_config *config = NULL;
|
||||
struct dhcp_netid known_id, iface_id, v6_id;
|
||||
- unsigned char *outmsgtypep;
|
||||
+ unsigned char outmsgtype;
|
||||
struct dhcp_vendor *vendor;
|
||||
struct dhcp_context *context_tmp;
|
||||
struct dhcp_mac *mac_opt;
|
||||
@@ -285,12 +285,13 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
v6_id.next = state->tags;
|
||||
state->tags = &v6_id;
|
||||
|
||||
- /* copy over transaction-id, and save pointer to message type */
|
||||
- if (!(outmsgtypep = put_opt6(inbuff, 4)))
|
||||
+ start_msg = save_counter(-1);
|
||||
+ /* copy over transaction-id */
|
||||
+ if (!put_opt6(inbuff, 4))
|
||||
return 0;
|
||||
start_opts = save_counter(-1);
|
||||
- state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
|
||||
-
|
||||
+ state->xid = inbuff[3] | inbuff[2] << 8 | inbuff[1] << 16;
|
||||
+
|
||||
/* We're going to be linking tags from all context we use.
|
||||
mark them as unused so we don't link one twice and break the list */
|
||||
for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
|
||||
@@ -336,7 +337,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
|
||||
|
||||
{
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6USEMULTI);
|
||||
put_opt6_string("Use multicast");
|
||||
@@ -600,11 +601,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
struct dhcp_netid *solicit_tags;
|
||||
struct dhcp_context *c;
|
||||
|
||||
- *outmsgtypep = DHCP6ADVERTISE;
|
||||
+ outmsgtype = DHCP6ADVERTISE;
|
||||
|
||||
if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
|
||||
{
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
state->lease_allocate = 1;
|
||||
o = new_opt6(OPTION6_RAPID_COMMIT);
|
||||
end_opt6(o);
|
||||
@@ -876,7 +877,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
int start = save_counter(-1);
|
||||
|
||||
/* set reply message type */
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
state->lease_allocate = 1;
|
||||
|
||||
log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
|
||||
@@ -992,7 +993,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
case DHCP6RENEW:
|
||||
{
|
||||
/* set reply message type */
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, "DHCPRENEW", NULL, NULL);
|
||||
|
||||
@@ -1104,7 +1105,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
int good_addr = 0;
|
||||
|
||||
/* set reply message type */
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
|
||||
|
||||
@@ -1168,7 +1169,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
|
||||
if (ignore)
|
||||
return 0;
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
tagif = add_options(state, 1);
|
||||
break;
|
||||
}
|
||||
@@ -1177,7 +1178,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
case DHCP6RELEASE:
|
||||
{
|
||||
/* set reply message type */
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, "DHCPRELEASE", NULL, NULL);
|
||||
|
||||
@@ -1242,7 +1243,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
case DHCP6DECLINE:
|
||||
{
|
||||
/* set reply message type */
|
||||
- *outmsgtypep = DHCP6REPLY;
|
||||
+ outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, "DHCPDECLINE", NULL, NULL);
|
||||
|
||||
@@ -1321,7 +1322,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
|
||||
}
|
||||
-
|
||||
+
|
||||
+ /* Fill in the message type. Note that we store the offset,
|
||||
+ not a direct pointer, since the packet memory may have been
|
||||
+ reallocated. */
|
||||
+ ((unsigned char *)(daemon->outpacket.iov_base))[start_msg] = outmsgtype;
|
||||
+
|
||||
log_tags(tagif, state->xid);
|
||||
log6_opts(0, state->xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1));
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
64
SOURCES/dnsmasq-2.87-log-root-writeable.patch
Normal file
64
SOURCES/dnsmasq-2.87-log-root-writeable.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From e342e4d5c3093d8dd9e2d622e46d36f67bfb4925 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Mon, 10 Jan 2022 12:34:42 +0100
|
||||
Subject: [PATCH] Add root group writeable flag to log file
|
||||
|
||||
Some systems strips even root process capability of writing to different
|
||||
users file. That include systemd under Fedora. When
|
||||
log-facility=/var/log/dnsmasq.log is used, log file with mode 0640
|
||||
is created. But restart then fails, because such log file can be used
|
||||
only when created new. Existing file cannot be opened by root when
|
||||
starting, causing fatal error. Avoid that by adding root group writeable flag.
|
||||
|
||||
Ensure group is always root when granting write access. If it is
|
||||
anything else, administrator has to configure correct rights.
|
||||
|
||||
(cherry picked from commit 1f8f78a49b8fd6b2862a3882053b1c6e6e111e5c)
|
||||
---
|
||||
src/log.c | 23 ++++++++++++++++++-----
|
||||
1 file changed, 18 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/log.c b/src/log.c
|
||||
index 1ec3447..bcd6e52 100644
|
||||
--- a/src/log.c
|
||||
+++ b/src/log.c
|
||||
@@ -100,10 +100,23 @@ int log_start(struct passwd *ent_pw, int errfd)
|
||||
/* If we're running as root and going to change uid later,
|
||||
change the ownership here so that the file is always owned by
|
||||
the dnsmasq user. Then logrotate can just copy the owner.
|
||||
- Failure of the chown call is OK, (for instance when started as non-root) */
|
||||
- if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0 &&
|
||||
- fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
- ret = errno;
|
||||
+ Failure of the chown call is OK, (for instance when started as non-root).
|
||||
+
|
||||
+ If we've created a file with group-id root, we also make
|
||||
+ the file group-writable. This gives processes in the root group
|
||||
+ write access to the file and avoids the problem that on some systems,
|
||||
+ once the file is owned by the dnsmasq user, it can't be written
|
||||
+ whilst dnsmasq is running as root during startup.
|
||||
+ */
|
||||
+ if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0)
|
||||
+ {
|
||||
+ struct stat ls;
|
||||
+ if (getgid() == 0 && fstat(log_fd, &ls) == 0 && ls.st_gid == 0 &&
|
||||
+ (ls.st_mode & S_IWGRP) == 0)
|
||||
+ (void)fchmod(log_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
+ if (fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
+ ret = errno;
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -118,7 +131,7 @@ int log_reopen(char *log_file)
|
||||
/* NOTE: umask is set to 022 by the time this gets called */
|
||||
|
||||
if (log_file)
|
||||
- log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
|
||||
+ log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
|
||||
else
|
||||
{
|
||||
#if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__)
|
||||
--
|
||||
2.40.1
|
||||
|
45
SOURCES/dnsmasq-2.89-edns0-size.patch
Normal file
45
SOURCES/dnsmasq-2.89-edns0-size.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 9d8270be2e2b31437684f2d87add9a28a41f0c75 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Tue, 7 Mar 2023 22:07:46 +0000
|
||||
Subject: [PATCH] Set the default maximum DNS UDP packet size to 1232.
|
||||
|
||||
http://www.dnsflagday.net/2020/ refers.
|
||||
|
||||
Thanks to Xiang Li for the prompt.
|
||||
|
||||
(cherry picked from commit eb92fb32b746f2104b0f370b5b295bb8dd4bd5e5)
|
||||
---
|
||||
man/dnsmasq.8 | 3 ++-
|
||||
src/config.h | 2 +-
|
||||
2 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
|
||||
index fce580f..4b0b180 100644
|
||||
--- a/man/dnsmasq.8
|
||||
+++ b/man/dnsmasq.8
|
||||
@@ -171,7 +171,8 @@ to zero completely disables DNS function, leaving only DHCP and/or TFTP.
|
||||
.TP
|
||||
.B \-P, --edns-packet-max=<size>
|
||||
Specify the largest EDNS.0 UDP packet which is supported by the DNS
|
||||
-forwarder. Defaults to 4096, which is the RFC5625-recommended size.
|
||||
+forwarder. Defaults to 1232, which is the recommended size following the
|
||||
+DNS flag day in 2020. Only increase if you know what you are doing.
|
||||
.TP
|
||||
.B \-Q, --query-port=<query_port>
|
||||
Send outbound DNS queries from, and listen for their replies on, the
|
||||
diff --git a/src/config.h b/src/config.h
|
||||
index 8c41943..62b7fa1 100644
|
||||
--- a/src/config.h
|
||||
+++ b/src/config.h
|
||||
@@ -19,7 +19,7 @@
|
||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
|
||||
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */
|
||||
-#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
||||
+#define EDNS_PKTSZ 1232 /* default max EDNS.0 UDP packet from from /dnsflagday.net/2020 */
|
||||
#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
|
||||
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
|
||||
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||
--
|
||||
2.39.2
|
||||
|
2318
SOURCES/dnsmasq-2.90-CVE-2023-50387-CVE-2023-50868.patch
Normal file
2318
SOURCES/dnsmasq-2.90-CVE-2023-50387-CVE-2023-50868.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,7 @@
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.79
|
||||
Release: 11%{?extraversion:.%{extraversion}}%{?dist}
|
||||
Release: 33%{?extraversion:.%{extraversion}}%{?dist}
|
||||
Summary: A lightweight DHCP/caching DNS server
|
||||
|
||||
License: GPLv2 or GPLv3
|
||||
@ -50,6 +50,56 @@ 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
|
||||
Patch22: dnsmasq-2.79-CVE-2020-25681.patch
|
||||
Patch23: dnsmasq-2.79-CVE-2020-25684.patch
|
||||
Patch24: dnsmasq-2.79-CVE-2020-25685.patch
|
||||
Patch25: dnsmasq-2.79-CVE-2020-25686.patch
|
||||
Patch26: dnsmasq-2.79-CVE-2020-25686-2.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=3f535da79e7a42104543ef5c7b5fa2bed819a78b
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=04490bf622ac84891aad6f2dd2edf83725decdee
|
||||
Patch27: dnsmasq-2.79-mixed-family-failed.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=b2ed691eb3ca6488a8878f5f3dd950a07b14a9db
|
||||
Patch28: dnsmasq-2.81-netlink-table.patch
|
||||
Patch29: dnsmasq-2.84-bind-dynamic-netlink.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=74d4fcd756a85bc1823232ea74334f7ccfb9d5d2
|
||||
Patch30: dnsmasq-2.85-CVE-2021-3448.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=03212e533b1e07aba30d2f4112009dc3af867ea5
|
||||
Patch31: dnsmasq-2.80-man-nameing.patch
|
||||
Patch32: dnsmasq-2.79-alternative-lease.patch
|
||||
Patch33: dnsmasq-2.86-dhcpv6-client-arch.patch
|
||||
# Downstream only patch; https://bugzilla.redhat.com/show_bug.cgi?id=1919894
|
||||
# Similar functionality is implemented since 2.86 in upstream, but introduced
|
||||
# several regressions. This implements just limited change in different way.
|
||||
Patch34: dnsmasq-2.79-server-domain-rh1919894.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=03345ecefeb0d82e3c3a4c28f27c3554f0611b39
|
||||
Patch35: dnsmasq-2.87-CVE-2022-0934.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=dded78b2338147daf69064d6d48c16b12744e441
|
||||
Patch36: dnsmasq-2.81-option6-ntp-server-suboption.patch
|
||||
# https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;h=3052ce208acf602f0163166dcefb7330d537cedb
|
||||
Patch37: dnsmasq-2.81-linux-SIOCGSTAMP.patch
|
||||
# Downstream only patch; fixes Patch34 change
|
||||
Patch38: dnsmasq-2.79-server-domain-fixup.patch
|
||||
# https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;h=f8c77edbdffb8ada7753ea9fa104f0f6da70cfe3
|
||||
Patch39: dnsmasq-2.81-dhcpv6-relay-link-address.patch
|
||||
# https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;h=eb92fb32b746f2104b0f370b5b295bb8dd4bd5e5
|
||||
Patch40: dnsmasq-2.89-edns0-size.patch
|
||||
# Downstream only patch; https://bugzilla.redhat.com/show_bug.cgi?id=2186481
|
||||
# Fixes issue in Patch4
|
||||
Patch41: dnsmasq-2.85-serv_domain-rh2186481.patch
|
||||
# Downstream only patch; https://bugzilla.redhat.com/show_bug.cgi?id=2186481
|
||||
# complements patch10
|
||||
Patch42: dnsmasq-2.85-serv_domain-rh2186481-2.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=1f8f78a49b8fd6b2862a3882053b1c6e6e111e5c
|
||||
Patch43: dnsmasq-2.87-log-root-writeable.patch
|
||||
# Downstream only patch; https://bugzilla.redhat.com/show_bug.cgi?id=2209031
|
||||
# complements patch42
|
||||
Patch44: dnsmasq-2.85-domain-blocklist-speedup.patch
|
||||
# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=dd33e98da09c487a58b6cb6693b8628c0b234a3b
|
||||
Patch45: dnsmasq-2.80-synth-domain-RHEL-15216.patch
|
||||
# https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=214a046f47b9f7dd56f5eef3a8678ccbd6e973b7
|
||||
Patch46: dnsmasq-2.90-CVE-2023-50387-CVE-2023-50868.patch
|
||||
|
||||
# This is workaround to nettle bug #1549190
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1549190
|
||||
@ -102,6 +152,33 @@ server's leases.
|
||||
%patch17 -p1 -b .rh1779187-2
|
||||
%patch18 -p1 -b .rh1779187-3
|
||||
%patch19 -p1 -b .rh1779187-4
|
||||
%patch20 -p1 -b .rh1816613
|
||||
%patch21 -p1 -b .rh1829448
|
||||
%patch22 -p1 -b .CVE-2020-25681
|
||||
%patch23 -p1 -b .CVE-2020-25684
|
||||
%patch24 -p1 -b .CVE-2020-25685
|
||||
%patch25 -p1 -b .CVE-2020-25686
|
||||
%patch26 -p1 -b .CVE-2020-25686-2
|
||||
%patch27 -p1 -b .rh1921153
|
||||
%patch28 -p1 -b .rh1887649-table
|
||||
%patch29 -p1 -b .rh1887649
|
||||
%patch30 -p1 -b .CVE-2021-3448
|
||||
%patch31 -p1 -b .rh1947039
|
||||
%patch32 -p1 -b .rh1998448
|
||||
%patch33 -p1 -b .dhcpv6-client-arch
|
||||
%patch34 -p1 -b .rh1919894
|
||||
%patch35 -p1 -b .CVE-2022-0934
|
||||
%patch36 -p1 -b .rh2049691
|
||||
%patch37 -p1 -b .SIOCGSTAMP
|
||||
%patch38 -p1 -b .rh2120357
|
||||
%patch39 -p1 -b .rh2169355
|
||||
%patch40 -p1 -b .CVE-2023-28450
|
||||
%patch41 -p1 -b .rh2186481
|
||||
%patch42 -p1 -b .rh2186481-2
|
||||
%patch43 -p1 -b .rh2156789
|
||||
%patch44 -p1 -b .rh2209031
|
||||
%patch45 -p1 -b .RHEL-15216
|
||||
%patch46 -p1 -b .CVE-2023-50387-CVE-2023-50868
|
||||
|
||||
# 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
|
||||
@ -167,11 +244,10 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/dnsmasq.conf
|
||||
|
||||
%pre
|
||||
#precreate users so that rpm can install files owned by that user
|
||||
%sysusers_create_inline %(cat %{SOURCE2})
|
||||
%sysusers_create_package %{name} %{SOURCE2}
|
||||
|
||||
%post
|
||||
#https://fedoraproject.org/wiki/Changes/SystemdSysusers
|
||||
%sysusers_create
|
||||
%systemd_post dnsmasq.service
|
||||
|
||||
%preun
|
||||
@ -202,6 +278,76 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/dnsmasq.conf
|
||||
%{_mandir}/man1/dhcp_*
|
||||
|
||||
%changelog
|
||||
* Mon Mar 18 2024 Tomas Korbar <tkorbar@redhat.com> - 2.79-33
|
||||
- Fix CVE 2023-50387 and CVE 2023-50868
|
||||
- Resolves: RHEL-25667
|
||||
- Resolves: RHEL-25629
|
||||
|
||||
* Wed Nov 01 2023 Petr Menšík <pemensik@redhat.com> - 2.79-32
|
||||
- Do not crash on invalid domain in --synth-domain option (RHEL-15216)
|
||||
|
||||
* Wed Jun 14 2023 Petr Menšík <pemensik@redhat.com> - 2.79-31
|
||||
- Do not create and search --local and --address=/x/# domains (#2233542)
|
||||
|
||||
* Wed Jun 14 2023 Petr Menšík <pemensik@redhat.com> - 2.79-30
|
||||
- Make create logfile writeable by root (#2156789)
|
||||
|
||||
* Wed May 10 2023 Petr Menšík <pemensik@redhat.com> - 2.79-29
|
||||
- Fix also dynamically set resolvers over dbus (#2186481)
|
||||
|
||||
* Fri Apr 21 2023 Petr Menšík <pemensik@redhat.com> - 2.79-28
|
||||
- Correct possible crashes when server=/example.net/# is used (#2186481)
|
||||
|
||||
* Mon Apr 03 2023 Petr Menšík <pemensik@redhat.com> - 2.79-27
|
||||
- Limit offered EDNS0 size to 1232 (CVE-2023-28450)
|
||||
|
||||
* Wed Feb 15 2023 Petr Menšík <pemensik@redhat.com> - 2.79-26
|
||||
- Avoid DHCPv6 relayed replies with Client Link-Layer Address (#2169355)
|
||||
|
||||
* Thu Jan 26 2023 Petr Menšík <pemensik@redhat.com> - 2.79-25
|
||||
- Use upstream change for CVE-2022-0934 (#2164859)
|
||||
|
||||
* Mon Aug 22 2022 Petr Menšík <pemensik@redhat.com> - 2.79-24
|
||||
- Prevent endless loop in forward_query (#2120357)
|
||||
|
||||
* Thu May 12 2022 Petr Menšík <pemensik@redhat.com> - 2.79-23
|
||||
- Add IPv6 ntp-server suboptions support (#2049691)
|
||||
|
||||
* Fri Mar 25 2022 Petr Menšík <pemensik@redhat.com> - 2.79-22
|
||||
- Prevent use after free in dhcp6_no_relay (CVE-2022-0934)
|
||||
|
||||
* Thu Jan 27 2022 Petr Menšík <pemensik@redhat.com> - 2.79-21
|
||||
- Send queries only to best domain-specific server (#1919894)
|
||||
|
||||
* Mon Sep 20 2021 Petr Menšík <pemensik@redhat.com> - 2.79-20
|
||||
- Offer alternate DHCPv6 address if requested is already leased (#1998448)
|
||||
|
||||
* Tue Jun 29 2021 Petr Menšík <pemensik@redhat.com> - 2.79-19
|
||||
- Correct typo in man page (#1947039)
|
||||
|
||||
* Thu Mar 18 2021 Petr Menšík <pemensik@redhat.com> - 2.79-18
|
||||
- Properly randomize outgoing ports also with bound interface (CVE-2021-3448)
|
||||
|
||||
* Fri Feb 12 2021 Petr Menšík <pemensik@redhat.com> - 2.79-17
|
||||
- Fix sporadic bind-dynamic failures (#1887649)
|
||||
|
||||
* Wed Jan 27 2021 Petr Menšík <pemensik@redhat.com> - 2.79-16
|
||||
- Fix network errors on queries both from ipv4 and ipv6 (#1921153)
|
||||
|
||||
* Wed Nov 25 2020 Petr Menšík <pemensik@redhat.com> - 2.79-15
|
||||
- Fix various issues in dnssec validation (CVE-2020-25681)
|
||||
- Accept responses only on correct sockets (CVE-2020-25684)
|
||||
- Use strong verification on queries (CVE-2020-25685)
|
||||
|
||||
* Wed Aug 26 2020 Tomas Korbar <tkorbar@redhat.com> - 2.79-14
|
||||
- Honor sysusers.d during installation (#1819684)
|
||||
|
||||
* 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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user