mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-27 03:07:43 +02:00
Merge remote-tracking branch 'mfischer/dnsmasq' into next
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org> Conflicts: lfs/dnsmasq
This commit is contained in:
@@ -0,0 +1,331 @@
|
||||
From a77cec8d58231d71cbc26615f0c0f0292c09ef54 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Fri, 8 May 2015 16:25:38 +0100
|
||||
Subject: [PATCH] Handle UDP packet loss when fragmentation of large packets
|
||||
is broken.
|
||||
|
||||
---
|
||||
CHANGELOG | 6 ++++++
|
||||
src/config.h | 1 +
|
||||
src/dnsmasq.h | 5 +++--
|
||||
src/dnssec.c | 11 +++++++++--
|
||||
src/forward.c | 37 +++++++++++++++++++++++++++++--------
|
||||
src/network.c | 1 +
|
||||
src/option.c | 18 +++++++++++-------
|
||||
src/rfc1035.c | 22 ++++++----------------
|
||||
8 files changed, 66 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/CHANGELOG b/CHANGELOG
|
||||
index af2b22c..d8fc57a 100644
|
||||
--- a/CHANGELOG
|
||||
+++ b/CHANGELOG
|
||||
@@ -109,6 +109,12 @@ version 2.73
|
||||
by quiet-dhcp6. Thanks to J. Pablo Abonia for
|
||||
spotting the problem.
|
||||
|
||||
+ Try and handle net connections with broken fragmentation
|
||||
+ that lose large UDP packets. If a server times out,
|
||||
+ reduce the maximum UDP packet size field in the EDNS0
|
||||
+ header to 1280 bytes. If it then answers, make that
|
||||
+ change permanent.
|
||||
+
|
||||
|
||||
version 2.72
|
||||
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
|
||||
diff --git a/src/config.h b/src/config.h
|
||||
index 8def6f2..f75fe9d 100644
|
||||
--- a/src/config.h
|
||||
+++ b/src/config.h
|
||||
@@ -19,6 +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 EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
||||
+#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
|
||||
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
|
||||
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
||||
index 824a860..ab16f79 100644
|
||||
--- a/src/dnsmasq.h
|
||||
+++ b/src/dnsmasq.h
|
||||
@@ -504,7 +504,7 @@ struct server {
|
||||
char interface[IF_NAMESIZE+1];
|
||||
struct serverfd *sfd;
|
||||
char *domain; /* set if this server only handles a domain. */
|
||||
- int flags, tcpfd;
|
||||
+ int flags, tcpfd, edns_pktsz;
|
||||
unsigned int queries, failed_queries;
|
||||
#ifdef HAVE_LOOP
|
||||
u32 uid;
|
||||
@@ -594,6 +594,7 @@ struct hostsfile {
|
||||
#define FREC_DO_QUESTION 64
|
||||
#define FREC_ADDED_PHEADER 128
|
||||
#define FREC_CHECK_NOSIGN 256
|
||||
+#define FREC_TEST_PKTSZ 512
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
#define HASH_SIZE 20 /* SHA-1 digest size */
|
||||
@@ -1148,7 +1149,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
|
||||
#endif
|
||||
|
||||
/* dnssec.c */
|
||||
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr);
|
||||
+size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
|
||||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer, int *nons);
|
||||
diff --git a/src/dnssec.c b/src/dnssec.c
|
||||
index a9e1215..e91d7c2 100644
|
||||
--- a/src/dnssec.c
|
||||
+++ b/src/dnssec.c
|
||||
@@ -2162,10 +2162,12 @@ int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
|
||||
}
|
||||
}
|
||||
|
||||
-size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
|
||||
+size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class,
|
||||
+ int type, union mysockaddr *addr, int edns_pktsz)
|
||||
{
|
||||
unsigned char *p;
|
||||
char *types = querystr("dnssec-query", type);
|
||||
+ size_t ret;
|
||||
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
|
||||
@@ -2194,7 +2196,12 @@ size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, i
|
||||
PUTSHORT(type, p);
|
||||
PUTSHORT(class, p);
|
||||
|
||||
- return add_do_bit(header, p - (unsigned char *)header, end);
|
||||
+ ret = add_do_bit(header, p - (unsigned char *)header, end);
|
||||
+
|
||||
+ if (find_pseudoheader(header, ret, NULL, &p, NULL))
|
||||
+ PUTSHORT(edns_pktsz, p);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/* Go through a domain name, find "pointers" and fix them up based on how many bytes
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index a8e403c..592243f 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -253,6 +253,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
void *hash = &crc;
|
||||
#endif
|
||||
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
+ unsigned char *pheader;
|
||||
|
||||
(void)do_bit;
|
||||
|
||||
@@ -261,19 +262,32 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
forward = NULL;
|
||||
else if (forward || (hash && (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.
|
||||
+ If that generates an answer, it will become the new default
|
||||
+ for this server */
|
||||
+ forward->flags |= FREC_TEST_PKTSZ;
|
||||
+
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* If we've already got an answer to this query, but we're awaiting keys for validation,
|
||||
there's no point retrying the query, retry the key query instead...... */
|
||||
if (forward->blocking_query)
|
||||
{
|
||||
int fd;
|
||||
-
|
||||
+
|
||||
+ forward->flags &= ~FREC_TEST_PKTSZ;
|
||||
+
|
||||
while (forward->blocking_query)
|
||||
forward = forward->blocking_query;
|
||||
+
|
||||
+ forward->flags |= FREC_TEST_PKTSZ;
|
||||
|
||||
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||||
plen = forward->stash_len;
|
||||
|
||||
+ if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
|
||||
+ PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : forward->sentto->edns_pktsz, pheader);
|
||||
+
|
||||
if (forward->sentto->addr.sa.sa_family == AF_INET)
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (struct all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -417,7 +431,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
plen = new_plen;
|
||||
}
|
||||
#endif
|
||||
-
|
||||
+
|
||||
while (1)
|
||||
{
|
||||
/* only send to servers dealing with our domain.
|
||||
@@ -464,6 +478,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+
|
||||
+ if (find_pseudoheader(header, plen, NULL, &pheader, NULL))
|
||||
+ PUTSHORT((forward->flags & FREC_TEST_PKTSZ) ? SAFE_PKTSZ : start->edns_pktsz, pheader);
|
||||
|
||||
if (retry_send(sendto(fd, (char *)header, plen, 0,
|
||||
&start->addr.sa,
|
||||
@@ -760,7 +777,6 @@ void reply_query(int fd, int family, time_t now)
|
||||
}
|
||||
|
||||
server = forward->sentto;
|
||||
-
|
||||
if ((forward->sentto->flags & SERV_TYPE) == 0)
|
||||
{
|
||||
if (RCODE(header) == REFUSED)
|
||||
@@ -781,7 +797,12 @@ void reply_query(int fd, int family, time_t now)
|
||||
if (!option_bool(OPT_ALL_SERVERS))
|
||||
daemon->last_server = server;
|
||||
}
|
||||
-
|
||||
+
|
||||
+ /* We tried resending to this server with a smaller maximum size and got an answer.
|
||||
+ Make that permanent. */
|
||||
+ if (server && (forward->flags & FREC_TEST_PKTSZ))
|
||||
+ server->edns_pktsz = SAFE_PKTSZ;
|
||||
+
|
||||
/* If the answer is an error, keep the forward record in place in case
|
||||
we get a good reply from another server. Kill it when we've
|
||||
had replies from all to avoid filling the forwarding table when
|
||||
@@ -890,7 +911,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
{
|
||||
new->flags |= FREC_DNSKEY_QUERY;
|
||||
nn = dnssec_generate_query(header, ((char *) header) + daemon->packet_buff_sz,
|
||||
- daemon->keyname, forward->class, T_DNSKEY, &server->addr);
|
||||
+ daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -899,7 +920,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
else
|
||||
new->flags |= FREC_DS_QUERY;
|
||||
nn = dnssec_generate_query(header,((char *) header) + daemon->packet_buff_sz,
|
||||
- daemon->keyname, forward->class, T_DS, &server->addr);
|
||||
+ 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);
|
||||
@@ -1526,7 +1547,7 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
|
||||
|
||||
/* Can't find it in the cache, have to send a query */
|
||||
|
||||
- m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr);
|
||||
+ m = dnssec_generate_query(header, ((char *) header) + 65536, name_start, class, T_DS, &server->addr, server->edns_pktsz);
|
||||
|
||||
*length = htons(m);
|
||||
|
||||
@@ -1638,7 +1659,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
|
||||
another_tcp_key:
|
||||
m = dnssec_generate_query(new_header, ((char *) new_header) + 65536, keyname, class,
|
||||
- new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr);
|
||||
+ new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
|
||||
|
||||
*length = htons(m);
|
||||
|
||||
diff --git a/src/network.c b/src/network.c
|
||||
index 992f023..a1d90c8 100644
|
||||
--- a/src/network.c
|
||||
+++ b/src/network.c
|
||||
@@ -1396,6 +1396,7 @@ void add_update_server(int flags,
|
||||
serv->domain = domain_str;
|
||||
serv->next = next;
|
||||
serv->queries = serv->failed_queries = 0;
|
||||
+ serv->edns_pktsz = daemon->edns_pktsz;
|
||||
#ifdef HAVE_LOOP
|
||||
serv->uid = rand32();
|
||||
#endif
|
||||
diff --git a/src/option.c b/src/option.c
|
||||
index f91cfbb..c7add88 100644
|
||||
--- a/src/option.c
|
||||
+++ b/src/option.c
|
||||
@@ -4498,15 +4498,19 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
{
|
||||
struct server *tmp;
|
||||
for (tmp = daemon->servers; tmp; tmp = tmp->next)
|
||||
- if (!(tmp->flags & SERV_HAS_SOURCE))
|
||||
- {
|
||||
- if (tmp->source_addr.sa.sa_family == AF_INET)
|
||||
- tmp->source_addr.in.sin_port = htons(daemon->query_port);
|
||||
+ {
|
||||
+ tmp->edns_pktsz = daemon->edns_pktsz;
|
||||
+
|
||||
+ if (!(tmp->flags & SERV_HAS_SOURCE))
|
||||
+ {
|
||||
+ if (tmp->source_addr.sa.sa_family == AF_INET)
|
||||
+ tmp->source_addr.in.sin_port = htons(daemon->query_port);
|
||||
#ifdef HAVE_IPV6
|
||||
- else if (tmp->source_addr.sa.sa_family == AF_INET6)
|
||||
- tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
|
||||
+ else if (tmp->source_addr.sa.sa_family == AF_INET6)
|
||||
+ tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
|
||||
#endif
|
||||
- }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
if (daemon->if_addrs)
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index 5828055..8b1709d 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -552,7 +552,7 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
|
||||
return plen;
|
||||
*p++ = 0; /* empty name */
|
||||
PUTSHORT(T_OPT, p);
|
||||
- PUTSHORT(daemon->edns_pktsz, p); /* max packet length */
|
||||
+ PUTSHORT(SAFE_PKTSZ, p); /* max packet length, this will be overwritten */
|
||||
PUTSHORT(0, p); /* extended RCODE and version */
|
||||
PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
|
||||
lenp = p;
|
||||
@@ -1537,7 +1537,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
unsigned short flag;
|
||||
int q, ans, anscount = 0, addncount = 0;
|
||||
int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
|
||||
- int is_sign;
|
||||
struct crec *crecp;
|
||||
int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
|
||||
struct mx_srv_record *rec;
|
||||
@@ -1557,28 +1556,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
forward rather than answering from the cache, which doesn't include
|
||||
security information, unless we're in DNSSEC validation mode. */
|
||||
|
||||
- if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
|
||||
+ if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
|
||||
{
|
||||
- unsigned short udpsz, flags;
|
||||
- unsigned char *psave = pheader;
|
||||
-
|
||||
+ unsigned short flags;
|
||||
+
|
||||
have_pseudoheader = 1;
|
||||
|
||||
- GETSHORT(udpsz, pheader);
|
||||
- pheader += 2; /* ext_rcode */
|
||||
+ pheader += 4; /* udp size, ext_rcode */
|
||||
GETSHORT(flags, pheader);
|
||||
|
||||
if ((sec_reqd = flags & 0x8000))
|
||||
*do_bit = 1;/* do bit */
|
||||
- *ad_reqd = 1;
|
||||
-
|
||||
- /* If our client is advertising a larger UDP packet size
|
||||
- than we allow, trim it so that we don't get an overlarge
|
||||
- response from upstream */
|
||||
-
|
||||
- if (!is_sign && (udpsz > daemon->edns_pktsz))
|
||||
- PUTSHORT(daemon->edns_pktsz, psave);
|
||||
|
||||
+ *ad_reqd = 1;
|
||||
dryrun = 1;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
@@ -0,0 +1,58 @@
|
||||
From b059c96dc69dfe3055c5b32b078a05c53b11ebb3 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Fri, 8 May 2015 20:25:51 +0100
|
||||
Subject: [PATCH] Check IPv4-mapped IPv6 addresses with --stop-rebind.
|
||||
|
||||
---
|
||||
CHANGELOG | 3 +++
|
||||
src/rfc1035.c | 21 +++++++++++++++++----
|
||||
2 files changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/CHANGELOG b/CHANGELOG
|
||||
index d8fc57a..94a521f 100644
|
||||
--- a/CHANGELOG
|
||||
+++ b/CHANGELOG
|
||||
@@ -115,6 +115,9 @@ version 2.73
|
||||
header to 1280 bytes. If it then answers, make that
|
||||
change permanent.
|
||||
|
||||
+ Check IPv4-mapped IPv6 addresses when --stop-rebind
|
||||
+ is active. Thanks to Jordan Milne for spotting this.
|
||||
+
|
||||
|
||||
version 2.72
|
||||
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index 8b1709d..5e3f566 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -1117,10 +1117,23 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
memcpy(&addr, p1, addrlen);
|
||||
|
||||
/* check for returned address in private space */
|
||||
- if (check_rebind &&
|
||||
- (flags & F_IPV4) &&
|
||||
- private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
||||
- return 1;
|
||||
+ if (check_rebind)
|
||||
+ {
|
||||
+ if ((flags & F_IPV4) &&
|
||||
+ private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
||||
+ return 1;
|
||||
+
|
||||
+#ifdef HAVE_IPV6
|
||||
+ if ((flags & F_IPV6) &&
|
||||
+ IN6_IS_ADDR_V4MAPPED(&addr.addr.addr6))
|
||||
+ {
|
||||
+ struct in_addr v4;
|
||||
+ v4.s_addr = ((const uint32_t *) (&addr.addr.addr6))[3];
|
||||
+ if (private_net(v4, !option_bool(OPT_LOCAL_REBIND)))
|
||||
+ return 1;
|
||||
+ }
|
||||
+#endif
|
||||
+ }
|
||||
|
||||
#ifdef HAVE_IPSET
|
||||
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
||||
--
|
||||
1.7.10.4
|
||||
@@ -26,4 +26,3 @@ index 592243fd4d35..74e5ab66c423 100644
|
||||
/* If the answer is an error, keep the forward record in place in case
|
||||
--
|
||||
2.1.0
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
From 585840b03365372679907f175b07a01c9d621ae0 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Wed, 13 May 2015 12:35:57 +0100
|
||||
Subject: [PATCH] Pointer to mail-archive mailing list mirror in doc.html.
|
||||
|
||||
---
|
||||
doc.html | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc.html b/doc.html
|
||||
index 92c9d0d..54f59bb 100644
|
||||
--- a/doc.html
|
||||
+++ b/doc.html
|
||||
@@ -74,7 +74,9 @@ for details.
|
||||
There is a dnsmasq mailing list at <A
|
||||
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
|
||||
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
|
||||
-first location for queries, bugreports, suggestions etc.
|
||||
+first location for queries, bugreports, suggestions etc. The list is mirrored, with a
|
||||
+search facility, at <A HREF="https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/">
|
||||
+https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/</A>.
|
||||
You can contact me at <A
|
||||
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
||||
@@ -197,4 +197,3 @@ index 55526443dc84..a10e499ef768 100644
|
||||
if (optno == OPTION_SNAME && done_server)
|
||||
--
|
||||
2.1.0
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 62018e1f720fa11e83879111a4b1b3753b5c25bb Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Thu, 14 May 2015 21:30:00 +0100
|
||||
Subject: [PATCH] Use correct DHCP context for PXE-proxy server-id.
|
||||
|
||||
---
|
||||
src/rfc2131.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/rfc2131.c b/src/rfc2131.c
|
||||
index b95f9be..70d1e59 100644
|
||||
--- a/src/rfc2131.c
|
||||
+++ b/src/rfc2131.c
|
||||
@@ -888,10 +888,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
|
||||
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
|
||||
- option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
|
||||
+ option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
|
||||
pxe_misc(mess, end, uuid);
|
||||
prune_vendor_opts(tagif_netid);
|
||||
- do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||
+ do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||
|
||||
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
--
|
||||
1.7.10.4
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
From 5d07d77e75e0f02bc0a8f6029ffbc8b371fa804e Mon Sep 17 00:00:00 2001
|
||||
From: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Date: Fri, 15 May 2015 18:13:06 +0100
|
||||
Subject: [PATCH] Fix buffer overflow introduced in 2.73rc6.
|
||||
|
||||
Fix off-by-one in code which checks for over-long domain names
|
||||
in received DNS packets. This enables buffer overflow attacks
|
||||
which can certainly crash dnsmasq and may allow for arbitrary
|
||||
code execution. The problem was introduced in commit b8f16556d,
|
||||
release 2.73rc6, so has not escaped into any stable release.
|
||||
Note that the off-by-one was in the label length determination,
|
||||
so the buffer can be overflowed by as many bytes as there are
|
||||
labels in the name - ie, many.
|
||||
|
||||
Thanks to Ron Bowes, who used lcmatuf's afl-fuzz tool to find
|
||||
the problem.
|
||||
---
|
||||
src/rfc1035.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/rfc1035.c b/src/rfc1035.c
|
||||
index 5e3f566..a95241f 100644
|
||||
--- a/src/rfc1035.c
|
||||
+++ b/src/rfc1035.c
|
||||
@@ -94,8 +94,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
count = 256;
|
||||
digs = ((count-1)>>2)+1;
|
||||
|
||||
- /* output is \[x<hex>/siz]. which is digs+6/7/8 chars */
|
||||
- namelen += digs+6;
|
||||
+ /* output is \[x<hex>/siz]. which is digs+7/8/9 chars */
|
||||
+ namelen += digs+7;
|
||||
if (count > 9)
|
||||
namelen++;
|
||||
if (count > 99)
|
||||
@@ -125,8 +125,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||
}
|
||||
else
|
||||
{ /* label_type = 0 -> label. */
|
||||
- namelen += l;
|
||||
- if (namelen+1 >= MAXDNAME)
|
||||
+ namelen += l + 1; /* include period */
|
||||
+ if (namelen >= MAXDNAME)
|
||||
return 0;
|
||||
if (!CHECK_LEN(header, p, plen, l))
|
||||
return 0;
|
||||
--
|
||||
1.7.10.4
|
||||
|
||||
Reference in New Issue
Block a user