aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/dnsmasq/patches/0020-Futher-address-union-tidying.patch
diff options
context:
space:
mode:
authorKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>2018-12-17 16:36:44 +0000
committerKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>2019-01-16 15:39:54 +0000
commit7541d30c9c2946fe112d7966f9d1e7456725c324 (patch)
treea1b250d30b31700e8c9bb77d511c9c76646700e8 /package/network/services/dnsmasq/patches/0020-Futher-address-union-tidying.patch
parent63a2ed3ba5bca13db3029e6eb8aa0c35872b73b9 (diff)
downloadupstream-7541d30c9c2946fe112d7966f9d1e7456725c324.tar.gz
upstream-7541d30c9c2946fe112d7966f9d1e7456725c324.tar.bz2
upstream-7541d30c9c2946fe112d7966f9d1e7456725c324.zip
dnsmasq: backport latest pre2.81 patches
f52bb5b fix previous commit 18eac67 Fix entries in /etc/hosts disabling static leases. f8c77ed Fix removal of DHCP_CLIENT_MAC options from DHCPv6 relay replies. 4bf62f6 Tidy cache_blockdata_free() 9c0d445 Fix e7bfd556c079c8b5e7425aed44abc35925b24043 to actually work. 2896e24 Check for not(DS or DNSKEY) in is_outdated_cname_pointer() a90f09d Fix crash freeing negative SRV cache entries. 5b99eae Cache SRV records. 2daca52 Fix typo in ra-param man page section. 2c59473 File logic bug in cache-marshalling code. Introduced a couple of commits back. cc921df Remove nested struct/union in cache records and all_addr. ab194ed Futher address union tidying. 65a01b7 Tidy address-union handling: move class into explicit argument. bde4647 Tidy all_addr union, merge log and rcode fields. e7bfd55 Alter DHCP address selection after DECLINE in consec-addr mode. Avoid offering the same address after a recieving a DECLINE message to stop an infinite protocol loop. This has long been done in default address allocation mode: this adds similar behaviour when allocaing addresses consecutively. The most relevant fix for openwrt is 18eac67 (& my own local f52bb5b which fixes a missing bracket silly) To quote the patch: It is possible for a config entry to have one address family specified by a dhcp-host directive and the other added from /etc/hosts. This is especially common on OpenWrt because it uses odhcpd for DHCPv6 and IPv6 leases are imported into dnsmasq via a hosts file. To handle this case there need to be separate *_HOSTS flags for IPv4 and IPv6. Otherwise when the hosts file is reloaded it will clear the CONFIG_ADDR(6) flag which was set by the dhcp-host directive. Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Diffstat (limited to 'package/network/services/dnsmasq/patches/0020-Futher-address-union-tidying.patch')
-rw-r--r--package/network/services/dnsmasq/patches/0020-Futher-address-union-tidying.patch363
1 files changed, 363 insertions, 0 deletions
diff --git a/package/network/services/dnsmasq/patches/0020-Futher-address-union-tidying.patch b/package/network/services/dnsmasq/patches/0020-Futher-address-union-tidying.patch
new file mode 100644
index 0000000000..a5f17ec859
--- /dev/null
+++ b/package/network/services/dnsmasq/patches/0020-Futher-address-union-tidying.patch
@@ -0,0 +1,363 @@
+From ab194ed7ca433e4e2e8b2ec338bfa4e6aa886a4b Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Tue, 1 Jan 2019 01:35:30 +0000
+Subject: [PATCH 20/30] Futher address union tidying.
+
+Pass DNSKEY and DS data into cache_insert via the address argument,
+now these data types are included in struct all_addr.
+
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/cache.c | 116 ++++++++++++++++----------------------------------
+ src/dnsmasq.h | 26 +++++------
+ src/dnssec.c | 53 +++++++++++------------
+ 3 files changed, 73 insertions(+), 122 deletions(-)
+
+--- a/src/cache.c
++++ b/src/cache.c
+@@ -202,9 +202,9 @@ static void cache_hash(struct crec *crec
+ static void cache_blockdata_free(struct crec *crecp)
+ {
+ if (crecp->flags & F_DNSKEY)
+- blockdata_free(crecp->addr.key.keydata);
++ blockdata_free(crecp->addr.addr.addr.key.keydata);
+ else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
+- blockdata_free(crecp->addr.ds.keydata);
++ blockdata_free(crecp->addr.addr.addr.ds.keydata);
+ }
+ #endif
+
+@@ -659,33 +659,22 @@ void cache_end_insert(void)
+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
+ read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
+
+- if (flags & (F_IPV4 | F_IPV6))
++ if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS))
+ read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
+ #ifdef HAVE_DNSSEC
+- else if (flags & F_DNSKEY)
++ if (flags & F_DNSKEY)
+ {
+ read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.algo, sizeof(new_chain->addr.key.algo), 0);
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keytag, sizeof(new_chain->addr.key.keytag), 0);
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.flags, sizeof(new_chain->addr.key.flags), 0);
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keylen, sizeof(new_chain->addr.key.keylen), 0);
+- blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent);
++ blockdata_write(new_chain->addr.addr.addr.key.keydata, new_chain->addr.addr.addr.key.keylen, daemon->pipe_to_parent);
+ }
+ else if (flags & F_DS)
+ {
+ read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
+ /* A negative DS entry is possible and has no data, obviously. */
+ if (!(flags & F_NEG))
+- {
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.algo, sizeof(new_chain->addr.ds.algo), 0);
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keytag, sizeof(new_chain->addr.ds.keytag), 0);
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.digest, sizeof(new_chain->addr.ds.digest), 0);
+- read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keylen, sizeof(new_chain->addr.ds.keylen), 0);
+- blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent);
+- }
++ blockdata_write(new_chain->addr.addr.addr.ds.keydata, new_chain->addr.addr.addr.ds.keylen, daemon->pipe_to_parent);
+ }
+ #endif
+-
+ }
+ }
+
+@@ -736,11 +725,30 @@ int cache_recv_insert(time_t now, int fd
+
+ ttl = difftime(ttd, now);
+
+- if (flags & (F_IPV4 | F_IPV6))
++ if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS))
+ {
++ unsigned short class = C_IN;
++
+ if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
+ return 0;
+- crecp = really_insert(daemon->namebuff, &addr, C_IN, now, ttl, flags);
++
++#ifdef HAVE_DNSSEC
++ if (flags & F_DNSKEY)
++ {
++ if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
++ !(addr.addr.key.keydata = blockdata_read(fd, addr.addr.key.keylen)))
++ return 0;
++ }
++ else if (flags & F_DS)
++ {
++ if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
++ (flags & F_NEG) ||
++ !(addr.addr.key.keydata = blockdata_read(fd, addr.addr.key.keylen)))
++ return 0;
++ }
++#endif
++
++ crecp = really_insert(daemon->namebuff, &addr, class, now, ttl, flags);
+ }
+ else if (flags & F_CNAME)
+ {
+@@ -764,58 +772,6 @@ int cache_recv_insert(time_t now, int fd
+ }
+ }
+ }
+-#ifdef HAVE_DNSSEC
+- else if (flags & (F_DNSKEY | F_DS))
+- {
+- unsigned short class, keylen, keyflags, keytag;
+- unsigned char algo, digest;
+- struct blockdata *keydata;
+-
+- if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1))
+- return 0;
+-
+- crecp = really_insert(daemon->namebuff, NULL, class, now, ttl, flags);
+-
+- if (flags & F_DNSKEY)
+- {
+- if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) ||
+- !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) ||
+- !read_write(fd, (unsigned char *)&keyflags, sizeof(keyflags), 1) ||
+- !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) ||
+- !(keydata = blockdata_read(fd, keylen)))
+- return 0;
+- }
+- else if (!(flags & F_NEG))
+- {
+- if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) ||
+- !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) ||
+- !read_write(fd, (unsigned char *)&digest, sizeof(digest), 1) ||
+- !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) ||
+- !(keydata = blockdata_read(fd, keylen)))
+- return 0;
+- }
+-
+- if (crecp)
+- {
+- if (flags & F_DNSKEY)
+- {
+- crecp->addr.key.algo = algo;
+- crecp->addr.key.keytag = keytag;
+- crecp->addr.key.flags = flags;
+- crecp->addr.key.keylen = keylen;
+- crecp->addr.key.keydata = keydata;
+- }
+- else if (!(flags & F_NEG))
+- {
+- crecp->addr.ds.algo = algo;
+- crecp->addr.ds.keytag = keytag;
+- crecp->addr.ds.digest = digest;
+- crecp->addr.ds.keylen = keylen;
+- crecp->addr.ds.keydata = keydata;
+- }
+- }
+- }
+-#endif
+ }
+ }
+
+@@ -1290,15 +1246,15 @@ void cache_reload(void)
+ #ifdef HAVE_DNSSEC
+ for (ds = daemon->ds; ds; ds = ds->next)
+ if ((cache = whine_malloc(SIZEOF_POINTER_CREC)) &&
+- (cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
++ (cache->addr.addr.addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
+ {
+ cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
+ cache->ttd = daemon->local_ttl;
+ cache->name.namep = ds->name;
+- cache->addr.ds.keylen = ds->digestlen;
+- cache->addr.ds.algo = ds->algo;
+- cache->addr.ds.keytag = ds->keytag;
+- cache->addr.ds.digest = ds->digest_type;
++ cache->addr.addr.addr.ds.keylen = ds->digestlen;
++ cache->addr.addr.addr.ds.algo = ds->algo;
++ cache->addr.addr.addr.ds.keytag = ds->keytag;
++ cache->addr.addr.addr.ds.digest = ds->digest_type;
+ cache->uid = ds->class;
+ cache_hash(cache);
+ make_non_terminals(cache);
+@@ -1775,12 +1731,12 @@ void dump_cache(time_t now)
+ else if (cache->flags & F_DS)
+ {
+ if (!(cache->flags & F_NEG))
+- sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
+- cache->addr.ds.algo, cache->addr.ds.digest);
++ sprintf(a, "%5u %3u %3u", cache->addr.addr.addr.ds.keytag,
++ cache->addr.addr.addr.ds.algo, cache->addr.addr.addr.ds.digest);
+ }
+ else if (cache->flags & F_DNSKEY)
+- sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
+- cache->addr.key.algo, cache->addr.key.flags);
++ sprintf(a, "%5u %3u %3u", cache->addr.addr.addr.key.keytag,
++ cache->addr.addr.addr.key.algo, cache->addr.addr.addr.key.flags);
+ #endif
+ else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
+ {
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -277,14 +277,21 @@ struct all_addr {
+ union {
+ struct in_addr addr4;
+ struct in6_addr addr6;
++ struct {
++ struct blockdata *keydata;
++ unsigned short keylen, flags, keytag;
++ unsigned char algo;
++ } key;
++ struct {
++ struct blockdata *keydata;
++ unsigned short keylen, keytag;
++ unsigned char algo;
++ unsigned char digest;
++ } ds;
+ /* for log_query */
+ struct {
+ unsigned short keytag, algo, digest, rcode;
+ } log;
+- /* for cache_insert of DNSKEY, DS */
+- struct {
+- unsigned short class, type;
+- } dnssec;
+ } addr;
+ };
+
+@@ -414,17 +421,6 @@ struct crec {
+ } target;
+ unsigned int uid; /* 0 if union is interface-name */
+ } cname;
+- struct {
+- struct blockdata *keydata;
+- unsigned short keylen, flags, keytag;
+- unsigned char algo;
+- } key;
+- struct {
+- struct blockdata *keydata;
+- unsigned short keylen, keytag;
+- unsigned char algo;
+- unsigned char digest;
+- } ds;
+ } addr;
+ time_t ttd; /* time to die */
+ /* used as class if DNSKEY/DS, index to source for F_HOSTS */
+--- a/src/dnssec.c
++++ b/src/dnssec.c
+@@ -628,10 +628,10 @@ static int validate_rrset(time_t now, st
+ {
+ /* iterate through all possible keys 4035 5.3.1 */
+ for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
+- if (crecp->addr.key.algo == algo &&
+- crecp->addr.key.keytag == key_tag &&
++ if (crecp->addr.addr.addr.key.algo == algo &&
++ crecp->addr.addr.addr.key.keytag == key_tag &&
+ crecp->uid == (unsigned int)class &&
+- verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
++ verify(crecp->addr.addr.addr.key.keydata, crecp->addr.addr.addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
+ return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
+ }
+ }
+@@ -728,10 +728,10 @@ int dnssec_validate_by_ds(time_t now, st
+ const struct nettle_hash *hash;
+ int sigcnt, rrcnt;
+
+- if (recp1->addr.ds.algo == algo &&
+- recp1->addr.ds.keytag == keytag &&
++ if (recp1->addr.addr.addr.ds.algo == algo &&
++ recp1->addr.addr.addr.ds.keytag == keytag &&
+ recp1->uid == (unsigned int)class &&
+- (hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
++ (hash = hash_find(ds_digest_name(recp1->addr.addr.addr.ds.digest))) &&
+ hash_init(hash, &ctx, &digest))
+
+ {
+@@ -746,9 +746,9 @@ int dnssec_validate_by_ds(time_t now, st
+ from_wire(name);
+
+ if (!(recp1->flags & F_NEG) &&
+- recp1->addr.ds.keylen == (int)hash->digest_size &&
+- (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
+- memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
++ recp1->addr.addr.addr.ds.keylen == (int)hash->digest_size &&
++ (ds_digest = blockdata_retrieve(recp1->addr.addr.addr.ds.keydata, recp1->addr.addr.addr.ds.keylen, NULL)) &&
++ memcmp(ds_digest, digest, recp1->addr.addr.addr.ds.keylen) == 0 &&
+ explore_rrset(header, plen, class, T_DNSKEY, name, keyname, &sigcnt, &rrcnt) &&
+ sigcnt != 0 && rrcnt != 0 &&
+ validate_rrset(now, header, plen, class, T_DNSKEY, sigcnt, rrcnt, name, keyname,
+@@ -800,7 +800,13 @@ int dnssec_validate_by_ds(time_t now, st
+
+ if ((key = blockdata_alloc((char*)p, rdlen - 4)))
+ {
+- if (!(recp1 = cache_insert(name, &a, class, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
++ a.addr.key.keylen = rdlen - 4;
++ a.addr.key.keydata = key;
++ a.addr.key.algo = algo;
++ a.addr.key.keytag = keytag;
++ a.addr.key.flags = flags;
++
++ if (!cache_insert(name, &a, class, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK))
+ {
+ blockdata_free(key);
+ return STAT_BOGUS;
+@@ -813,12 +819,6 @@ int dnssec_validate_by_ds(time_t now, st
+ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu");
+ else
+ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %hu, algo %hu (not supported)");
+-
+- recp1->addr.key.keylen = rdlen - 4;
+- recp1->addr.key.keydata = key;
+- recp1->addr.key.algo = algo;
+- recp1->addr.key.keytag = keytag;
+- recp1->addr.key.flags = flags;
+ }
+ }
+ }
+@@ -915,8 +915,7 @@ int dnssec_validate_ds(time_t now, struc
+ int algo, digest, keytag;
+ unsigned char *psave = p;
+ struct blockdata *key;
+- struct crec *crecp;
+-
++
+ if (rdlen < 4)
+ return STAT_BOGUS; /* bad packet */
+
+@@ -926,7 +925,13 @@ int dnssec_validate_ds(time_t now, struc
+
+ if ((key = blockdata_alloc((char*)p, rdlen - 4)))
+ {
+- if (!(crecp = cache_insert(name, NULL, class, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
++ a.addr.ds.digest = digest;
++ a.addr.ds.keydata = key;
++ a.addr.ds.algo = algo;
++ a.addr.ds.keytag = keytag;
++ a.addr.ds.keylen = rdlen - 4;
++
++ if (!cache_insert(name, &a, class, now, ttl, F_FORWARD | F_DS | F_DNSSECOK))
+ {
+ blockdata_free(key);
+ return STAT_BOGUS;
+@@ -940,12 +945,6 @@ int dnssec_validate_ds(time_t now, struc
+ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu");
+ else
+ log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)");
+-
+- crecp->addr.ds.digest = digest;
+- crecp->addr.ds.keydata = key;
+- crecp->addr.ds.algo = algo;
+- crecp->addr.ds.keytag = keytag;
+- crecp->addr.ds.keylen = rdlen - 4;
+ }
+ }
+
+@@ -1711,8 +1710,8 @@ static int zone_status(char *name, int c
+ do
+ {
+ if (crecp->uid == (unsigned int)class &&
+- ds_digest_name(crecp->addr.ds.digest) &&
+- algo_digest_name(crecp->addr.ds.algo))
++ ds_digest_name(crecp->addr.addr.addr.ds.digest) &&
++ algo_digest_name(crecp->addr.addr.addr.ds.algo))
+ break;
+ }
+ while ((crecp = cache_find_by_name(crecp, keyname, now, F_DS)));