-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Truncated DNS/UDP responses when using getdns #495
Comments
@amialkow the formatting here has seriously screwed up your patch making it practically unreadable. Can you place the patch into a code block please? |
Hi. I am also using OpenWrt 19.07.6 with stubby/getdns/dnsmasq on my
router.
With *dig* (on Arch linux within *bind* package) I see no problems. I do
not use *nslookup* because it is deprecated.
Unfortunately i do not have an Amazon Smart Plug to test with.
*ARCH-PC% dig a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
<http://a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com> 127.0.0.1#5453*
; <<>> DiG 9.16.13 <<>> a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
127.0.0.1#5453
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11094
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. IN A
;; ANSWER SECTION:
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 34.232.233.94
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.221.81.122
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.224.51.158
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 52.204.38.169
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 52.45.85.193
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.227.79.178
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 54.159.58.62
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.225.102.27
;; Query time: 323 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: zo apr 04 20:11:02 CEST 2021
;; MSG SIZE rcvd: 535
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 61707
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;127.0.0.1#5453. IN A
;; AUTHORITY SECTION:
. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2021040401 1800
900 604800 86400
. 86400 IN RRSIG SOA 8 0 86400 20210417170000 20210404160000 14631 .
am6Wwo2pbSVSyiFv3lckzMdYb2QTZdR1FZ43GsqLgrK+L7WlbFGNpi4P
+pZ5BGdOiYOYeKk8GdzjqNb6NTE7Kf7Fsxxr7jz8zL+RMGJ3tVawRAKg
6hY5MIH9i/o0FI2wwUO7eMHUK96K36c9O2jBIdb5KcAtHXUZDctqUNxp
khWFkFYbtni35lPjXXDj6cVLRKrUMe0tQmZIVyID6w0hVWOs8pnwYokx
1FrrOpsXj3g11nT+SaGdZSZxuoQBHHWORUgMUckFT7i7gjG8bP0egmiZ
N8CQ8mpyn77Wpma+eNKpKqL3+LP5imAhx0hUVduMg4fi4120EZqCo0VY hdI5VQ==
. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
. 86400 IN RRSIG NSEC 8 0 86400 20210417170000 20210404160000 14631 .
ZyW+HnMRRV3Rq2aT87aZzOwpqVDlvUzEUh66EKsSavah/eJsvjQUa84b
TdXMIBgmUQgoxhzDJHR+spL7TLTE9M4zFh/51i4Pdt5PbdegdgyBybTB
X9JRCeJr3CDUBeTviBJq7qw3hFYqxZ+3vagjaVcoUZ5eCm62jw7Sp4Ya
inLhDya04NbNZF0uWraBzVW6SMf5spWzpuuJcksUtIM9ADB7mOShAcjE
RuHLGXQPgUdLSw/5wRvCgiR116rCci6oVCkHLiGsvoSTMvqK/bGtT8ao
CMGFimi2OAO7IU2UpSJINkZQSQ6tKDIdwLKL1dlh5PgHk7iGRY0gnYNS W74Xkw==
;; Query time: 83 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: zo apr 04 20:11:02 CEST 2021
;; MSG SIZE rcvd: 715
Op zo 4 apr. 2021 om 13:20 schreef jonathanunderwood <
***@***.***>:
… @amialkow <https://github.com/amialkow> the formatting here has seriously
screwed up your patch making it practically unreadable. Can you place the
patch into a code block please?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#495 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGDNGSKPL7OIDM7BEREQAZ3THBDQBANCNFSM4T247BOA>
.
|
Directly from the router with nslookup
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com:
;; Truncated, retrying in TCP mode.
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 3.208.180.40
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 34.205.151.123
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 3.211.26.133
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 52.0.23.67
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 52.0.132.142
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 3.215.2.150
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 52.6.207.226
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 54.146.80.152
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::22c8:ae37
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::22c3:67e4
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::22c2:b471
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::3d1:5e12
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::3de:c532
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::3437:920c
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::23ac:4caf
Name: a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
Address: 2406:da00:ff00::23ac:ae8b
Op zo 4 apr. 2021 om 20:22 schreef Han Vinke ***@***.***>:
… Hi. I am also using OpenWrt 19.07.6 with stubby/getdns/dnsmasq on my
router.
With *dig* (on Arch linux within *bind* package) I see no problems. I do
not use *nslookup* because it is deprecated.
Unfortunately i do not have an Amazon Smart Plug to test with.
*ARCH-PC% dig a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
<http://a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com> 127.0.0.1#5453*
; <<>> DiG 9.16.13 <<>> a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
127.0.0.1#5453
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11094
;; flags: qr rd ra; QUERY: 1, ANSWER: 8, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. IN A
;; ANSWER SECTION:
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 34.232.233.94
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.221.81.122
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.224.51.158
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 52.204.38.169
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 52.45.85.193
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.227.79.178
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 54.159.58.62
a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com. 60 IN A 3.225.102.27
;; Query time: 323 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: zo apr 04 20:11:02 CEST 2021
;; MSG SIZE rcvd: 535
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 61707
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;127.0.0.1#5453. IN A
;; AUTHORITY SECTION:
. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2021040401
1800 900 604800 86400
. 86400 IN RRSIG SOA 8 0 86400 20210417170000 20210404160000 14631 .
am6Wwo2pbSVSyiFv3lckzMdYb2QTZdR1FZ43GsqLgrK+L7WlbFGNpi4P
+pZ5BGdOiYOYeKk8GdzjqNb6NTE7Kf7Fsxxr7jz8zL+RMGJ3tVawRAKg
6hY5MIH9i/o0FI2wwUO7eMHUK96K36c9O2jBIdb5KcAtHXUZDctqUNxp
khWFkFYbtni35lPjXXDj6cVLRKrUMe0tQmZIVyID6w0hVWOs8pnwYokx
1FrrOpsXj3g11nT+SaGdZSZxuoQBHHWORUgMUckFT7i7gjG8bP0egmiZ
N8CQ8mpyn77Wpma+eNKpKqL3+LP5imAhx0hUVduMg4fi4120EZqCo0VY hdI5VQ==
. 86400 IN NSEC aaa. NS SOA RRSIG NSEC DNSKEY
. 86400 IN RRSIG NSEC 8 0 86400 20210417170000 20210404160000 14631 .
ZyW+HnMRRV3Rq2aT87aZzOwpqVDlvUzEUh66EKsSavah/eJsvjQUa84b
TdXMIBgmUQgoxhzDJHR+spL7TLTE9M4zFh/51i4Pdt5PbdegdgyBybTB
X9JRCeJr3CDUBeTviBJq7qw3hFYqxZ+3vagjaVcoUZ5eCm62jw7Sp4Ya
inLhDya04NbNZF0uWraBzVW6SMf5spWzpuuJcksUtIM9ADB7mOShAcjE
RuHLGXQPgUdLSw/5wRvCgiR116rCci6oVCkHLiGsvoSTMvqK/bGtT8ao
CMGFimi2OAO7IU2UpSJINkZQSQ6tKDIdwLKL1dlh5PgHk7iGRY0gnYNS W74Xkw==
;; Query time: 83 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: zo apr 04 20:11:02 CEST 2021
;; MSG SIZE rcvd: 715
Op zo 4 apr. 2021 om 13:20 schreef jonathanunderwood <
***@***.***>:
> @amialkow <https://github.com/amialkow> the formatting here has
> seriously screwed up your patch making it practically unreadable. Can you
> place the patch into a code block please?
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <#495 (comment)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AGDNGSKPL7OIDM7BEREQAZ3THBDQBANCNFSM4T247BOA>
> .
>
|
When using *dig* directly on the router by installing *bind-dig* I get
different results:
First with nslookup:
/etc/config$ nslookup a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
127.0.0.1#5453
nslookup: couldn't get address for '127.0.0.1#5453': not found
/etc/config$ nslookup a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com
127.0.0.1#5453
nslookup: couldn't get address for '127.0.0.1#5453': not found
/etc/config$ dig a1g7wmxwoovxaz.iot.us-east-1.amazonaws.com 127.0.0.1#5453
This nslookup fails completely. It says the address does not exist. And of
course it does.
Now with dig. Dig shows no tr flag :
[full_text.txt](https://github.com/getdnsapi/getdns/files/6263210/full_text.txt)
It seems the problem is with using nslookup instead of dig. On the internet
I found a link with a good explanation why nslookups might fail altogether:
see
https://archive.nanog.org/meetings/nanog52/presentations/Sunday/Sinatra-DNS-DNSSEC_tutorial-reallyfinal.pdf
Analysis of https://dnsviz.net/
![a1g7wmxwoovxaz iot us-east-1 amazonaws com-2021-04-06-08_41_12-UTC](https://user-images.githubusercontent.com/25613129/113684525-9c4dcc00-96c5-11eb-9c0d-d0629f50d3da.png)
|
Hi, Root of the issue is that getdns library unpacks responses from DNS server but does not implement name "compression" so resulting frames are too large for UDP and payload is removed. OpenWRT version of nslookup uses basic version UDP protocol, this is same as my Amazon plug. Code below implements simple domain name cache. Each time when name is stored in destination packet it puts name pointer, and it's offset into cache entry. During subsequent calls cache lookup is performed and in case of hit relative pointer name is stored. I'm considering two more improvements:
diff -Nru a/src/convert.c b/src/convert.c
--- a/src/convert.c 2020-02-28 06:39:53.000000000 -0800
+++ b/src/convert.c 2021-04-10 21:13:36.532084800 -0700
@@ -754,6 +754,7 @@
getdns_list *section;
getdns_dict *rr_dict;
getdns_bindata *qname;
+ name_cache_t name_cache = {0};
int remove_dnssec;
pkt_start = gldns_buffer_position(buf);
@@ -783,7 +784,7 @@
if (!getdns_dict_get_bindata(reply, "/question/qname", &qname) &&
!getdns_dict_get_int(reply, "/question/qtype", &qtype)) {
(void)getdns_dict_get_int(reply, "/question/qclass", &qclass);
- gldns_buffer_write(buf, qname->data, qname->size);
+ _getdns_rr_buffer_write_cached_name(buf, qname, &name_cache);
gldns_buffer_write_u16(buf, (uint16_t)qtype);
gldns_buffer_write_u16(buf, (uint16_t)qclass);
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_QDCOUNT_OFF, 1);
@@ -806,7 +807,7 @@
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
rr_type == GETDNS_RRTYPE_RRSIG)
continue;
- if (!_getdns_rr_dict2wire(rr_dict, buf))
+ if (!_getdns_rr_dict2wire_cache(rr_dict, buf, &name_cache))
n++;
}
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n);
diff -Nru a/src/rr-dict.c b/src/rr-dict.c
--- a/src/rr-dict.c 2020-02-28 06:39:53.000000000 -0800
+++ b/src/rr-dict.c 2021-04-10 21:17:45.682994949 -0700
@@ -1293,8 +1293,39 @@
return r != GETDNS_RETURN_NO_SUCH_LIST_ITEM ? r : GETDNS_RETURN_GOOD;
}
+void
+_getdns_rr_buffer_write_cached_name(gldns_buffer *buf, getdns_bindata *name, name_cache_t *name_cache)
+{
+ size_t name_size = name->size;
+ uint8_t *name_data = name->data;
+ if((NULL != name_cache) && (name_size > 2)) {
+ name_cache_entry_t *table_free, *entry_ptr;
+ table_free = entry_ptr = &name_cache->entry[name_cache->count];
+ name_cache_entry_t *table_start = &name_cache->entry[0];
+ // Search backward if name is already in cache
+ while(entry_ptr-- > table_start) {
+ if((entry_ptr->name->size == name_size) &&
+ !memcmp(entry_ptr->name->data, name_data, name_size)) {
+ gldns_buffer_write_u16(buf, (uint16_t)(0xc000 | entry_ptr->name_offset));
+ return;
+ }
+ }
+ unsigned name_offset = gldns_buffer_position(buf);
+ if ((name_cache->count < NAME_CACHE_ENTRIES) &&
+ (name_offset < 0xc000)) {
+ // Cache name
+ table_free->name = name;
+ table_free->name_offset = name_offset;
+ name_cache->count++;
+ }
+ }
+ gldns_buffer_write(buf, name_data, name_size);
+ return;
+}
+
getdns_return_t
-_getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
+_getdns_rr_dict2wire_cache(const getdns_dict *rr_dict, gldns_buffer *buf,
+ name_cache_t *name_cache)
{
getdns_return_t r = GETDNS_RETURN_GOOD;
getdns_bindata root = { 1, (void *)"" };
@@ -1325,7 +1356,7 @@
} else
return r;
}
- gldns_buffer_write(buf, name->data, name->size);
+ _getdns_rr_buffer_write_cached_name(buf, name, name_cache);
gldns_buffer_write_u16(buf, (uint16_t)rr_type);
(void) getdns_dict_get_int(rr_dict, "class", &rr_class);
diff -Nru a/src/rr-dict.h b/src/rr-dict.h
--- a/src/rr-dict.h 2020-02-28 06:39:53.000000000 -0800
+++ b/src/rr-dict.h 2021-04-10 21:13:36.532084800 -0700
@@ -143,8 +143,25 @@
const _getdns_rr_def *_getdns_rr_def_lookup(uint16_t rr_type);
-getdns_return_t _getdns_rr_dict2wire(
- const getdns_dict *rr_dict, gldns_buffer *buf);
+#define NAME_CACHE_ENTRIES 4
+
+typedef struct __name_cache_entry {
+ getdns_bindata *name;
+ unsigned name_offset;
+} name_cache_entry_t;
+
+typedef struct __name_cache {
+ unsigned count;
+ name_cache_entry_t entry[NAME_CACHE_ENTRIES];
+} name_cache_t;
+
+void _getdns_rr_buffer_write_cached_name(
+ gldns_buffer *buf, getdns_bindata *name, name_cache_t *name_cache);
+
+getdns_return_t _getdns_rr_dict2wire_cache(
+ const getdns_dict *rr_dict, gldns_buffer *buf, name_cache_t *name_cache);
+
+#define _getdns_rr_dict2wire(d, b) _getdns_rr_dict2wire_cache((d),(b), NULL)
const char *_getdns_rr_type_name(int rr_type); |
Hi,
diff --git a/src/convert.c b/src/convert.c
index 8dc44ddf..6dbd429a 100644
--- a/src/convert.c
+++ b/src/convert.c
@@ -823,6 +823,7 @@ _getdns_reply_dict2wire(
getdns_list *section;
getdns_dict *rr_dict;
getdns_bindata *qname;
+ name_cache_t name_cache = {0};
int remove_dnssec;
pkt_start = gldns_buffer_position(buf);
@@ -852,7 +853,7 @@ _getdns_reply_dict2wire(
if (!getdns_dict_get_bindata(reply, "/question/qname", &qname) &&
!getdns_dict_get_int(reply, "/question/qtype", &qtype)) {
(void)getdns_dict_get_int(reply, "/question/qclass", &qclass);
- gldns_buffer_write(buf, qname->data, qname->size);
+ _getdns_rr_buffer_write_cached_name(buf, qname, &name_cache);
gldns_buffer_write_u16(buf, (uint16_t)qtype);
gldns_buffer_write_u16(buf, (uint16_t)qclass);
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_QDCOUNT_OFF, 1);
@@ -875,7 +876,7 @@ _getdns_reply_dict2wire(
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
rr_type == GETDNS_RRTYPE_RRSIG)
continue;
- if (!_getdns_rr_dict2wire(rr_dict, buf))
+ if (!_getdns_rr_dict2wire_cache(rr_dict, buf, &name_cache))
n++;
}
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n);
diff --git a/src/rr-dict.c b/src/rr-dict.c
index fc675830..16813603 100644
--- a/src/rr-dict.c
+++ b/src/rr-dict.c
@@ -1293,8 +1293,39 @@ write_rdata_field(gldns_buffer *buf, uint8_t *rdata_start,
return r != GETDNS_RETURN_NO_SUCH_LIST_ITEM ? r : GETDNS_RETURN_GOOD;
}
+void
+_getdns_rr_buffer_write_cached_name(gldns_buffer *buf, getdns_bindata *name, name_cache_t *name_cache)
+{
+ size_t name_size = name->size;
+ uint8_t *name_data = name->data;
+ if((NULL != name_cache) && (name_size > 2)) {
+ unsigned count = name_cache->count;
+ name_cache_entry_t *entry_ptr = &name_cache->entry[(count < NAME_CACHE_ENTRIES)?count:NAME_CACHE_ENTRIES];
+ name_cache_entry_t *table_start = &name_cache->entry[0];
+ /* Search backward if name is already in cache */
+ while(entry_ptr-- > table_start) {
+ if((entry_ptr->name->size == name_size) &&
+ !memcmp(entry_ptr->name->data, name_data, name_size)) {
+ gldns_buffer_write_u16(buf, (uint16_t)(0xc000 | entry_ptr->name_offset));
+ return;
+ }
+ }
+ unsigned name_offset = gldns_buffer_position(buf);
+ if (name_offset < 0xc000) {
+ /* Cache name */
+ entry_ptr = &name_cache->entry[count % NAME_CACHE_ENTRIES];
+ entry_ptr->name = name;
+ entry_ptr->name_offset = name_offset;
+ name_cache->count = count + 1;
+ }
+ }
+ gldns_buffer_write(buf, name_data, name_size);
+ return;
+}
+
getdns_return_t
-_getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
+_getdns_rr_dict2wire_cache(const getdns_dict *rr_dict, gldns_buffer *buf,
+ name_cache_t *name_cache)
{
getdns_return_t r = GETDNS_RETURN_GOOD;
getdns_bindata root = { 1, (void *)"" };
@@ -1325,7 +1356,7 @@ _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
} else
return r;
}
- gldns_buffer_write(buf, name->data, name->size);
+ _getdns_rr_buffer_write_cached_name(buf, name, name_cache);
gldns_buffer_write_u16(buf, (uint16_t)rr_type);
(void) getdns_dict_get_int(rr_dict, "class", &rr_class);
@@ -1378,41 +1409,50 @@ _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
gldns_buffer_skip(buf, 2);
rdata_start = gldns_buffer_current(buf);
- for ( rd_def = rr_def->rdata
- , n_rdata_fields = rr_def->n_rdata_fields
- ; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) {
+ /* Special case CNAME payload */
+ if((rr_type == GETDNS_RRTYPE_CNAME) && (n_rdata_fields == 1) &&
+ (rd_def->type & GETDNS_RDF_BINDATA) && !(rd_def->type & GETDNS_RDF_REPEAT) &&
+ (GETDNS_RETURN_GOOD == (r = getdns_dict_get_bindata(rdata, rd_def->name, &rdata_raw)))) {
+
+ _getdns_rr_buffer_write_cached_name(buf, rdata_raw, name_cache);
+ } else {
- if (rd_def->type == GETDNS_RDF_REPEAT)
- break;
+ for ( rd_def = rr_def->rdata
+ , n_rdata_fields = rr_def->n_rdata_fields
+ ; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) {
- if ((r = write_rdata_field(buf,
- rdata_start, rd_def, rdata)))
- break;
- }
- if (n_rdata_fields == 0 || r) {
- /* pass */;
+ if (rd_def->type == GETDNS_RDF_REPEAT)
+ break;
- } else if ((r = getdns_dict_get_list(
- rdata, rd_def->name, &list))) {
- /* pass */;
+ if ((r = write_rdata_field(buf,
+ rdata_start, rd_def, rdata)))
+ break;
+ }
+ if (n_rdata_fields == 0 || r) {
+ /* pass */;
- } else for ( i = 0
- ; r == GETDNS_RETURN_GOOD
- ; i++) {
+ } else if ((r = getdns_dict_get_list(
+ rdata, rd_def->name, &list))) {
+ /* pass */;
- if ((r = getdns_list_get_dict(list, i, &rdata))) {
- if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
- r = GETDNS_RETURN_GOOD;
- break;
- }
- for ( rep_rd_def = rd_def + 1
- , rep_n_rdata_fields = n_rdata_fields - 1
- ; rep_n_rdata_fields
- ; rep_n_rdata_fields--, rep_rd_def++ ) {
+ } else for ( i = 0
+ ; r == GETDNS_RETURN_GOOD
+ ; i++) {
- if ((r = write_rdata_field(buf,
- rdata_start, rep_rd_def, rdata)))
+ if ((r = getdns_list_get_dict(list, i, &rdata))) {
+ if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
+ r = GETDNS_RETURN_GOOD;
break;
+ }
+ for ( rep_rd_def = rd_def + 1
+ , rep_n_rdata_fields = n_rdata_fields - 1
+ ; rep_n_rdata_fields
+ ; rep_n_rdata_fields--, rep_rd_def++ ) {
+
+ if ((r = write_rdata_field(buf,
+ rdata_start, rep_rd_def, rdata)))
+ break;
+ }
}
}
gldns_buffer_write_u16_at(buf, rdata_size_mark,
diff --git a/src/rr-dict.h b/src/rr-dict.h
index e19e0387..f0788021 100644
--- a/src/rr-dict.h
+++ b/src/rr-dict.h
@@ -143,8 +143,25 @@ typedef struct _getdns_rr_def {
const _getdns_rr_def *_getdns_rr_def_lookup(uint16_t rr_type);
-getdns_return_t _getdns_rr_dict2wire(
- const getdns_dict *rr_dict, gldns_buffer *buf);
+#define NAME_CACHE_ENTRIES 4
+
+typedef struct __name_cache_entry {
+ getdns_bindata *name;
+ unsigned name_offset;
+} name_cache_entry_t;
+
+typedef struct __name_cache {
+ unsigned count;
+ name_cache_entry_t entry[NAME_CACHE_ENTRIES];
+} name_cache_t;
+
+void _getdns_rr_buffer_write_cached_name(
+ gldns_buffer *buf, getdns_bindata *name, name_cache_t *name_cache);
+
+getdns_return_t _getdns_rr_dict2wire_cache(
+ const getdns_dict *rr_dict, gldns_buffer *buf, name_cache_t *name_cache);
+
+#define _getdns_rr_dict2wire(d, b) _getdns_rr_dict2wire_cache((d),(b), NULL)
const char *_getdns_rr_type_name(int rr_type);
Change in _getdns_rr_dict2wire with --ignore-all-space. Original code is put in else statement, diff just gets confused. @@ -1378,6 +1409,14 @@ _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
gldns_buffer_skip(buf, 2);
rdata_start = gldns_buffer_current(buf);
+ /* Special case CNAME payload */
+ if((rr_type == GETDNS_RRTYPE_CNAME) && (n_rdata_fields == 1) &&
+ (rd_def->type & GETDNS_RDF_BINDATA) && !(rd_def->type & GETDNS_RDF_REPEAT) &&
+ (GETDNS_RETURN_GOOD == (r = getdns_dict_get_bindata(rdata, rd_def->name, &rdata_raw)))) {
+
+ _getdns_rr_buffer_write_cached_name(buf, rdata_raw, name_cache);
+ } else {
+
for ( rd_def = rr_def->rdata
, n_rdata_fields = rr_def->n_rdata_fields
; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) {
@@ -1415,6 +1454,7 @@ _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
break;
}
}
+ }
gldns_buffer_write_u16_at(buf, rdata_size_mark,
(uint16_t)(gldns_buffer_position(buf)-rdata_size_mark-2));
} |
Looks like some great progress here - why not submit the patch as a pull request? |
@jonathanunderwood It looks tree is broken for long time, opened #504. I have few fixes in totally wrong order stashed together in #503. Failure of #505 is triggered by my changes. Apparently this is not the end. Slowly trying to cleanup this. |
Hi,
I experienced issue with Amazon Smart Plug not being able to obtain server address after enabling stubby 0.3.0/getdns 1.6.0 on my OpenWrt 19.07.4. Later I found that same issue exist with OpenWRT nslookup (below). In case of use getdns legacy dns UDP packet size limit is exceeded because because of no support for compacting repeating names in answers. Below is my very basic implementation of compacting scheme working for my case, it use only query name as reference. Please let me know if there are other interesting cases, I'm not DNS expert by any mean. Notice also I blindly changed all wire formatting functions not really understanding purpose. I can spend little more time and provide proper patch.
Regards,
Andy
Similar issue (as far as I see different closure):
#430 (comment)_
Query over stubby (truncated)
Direct query:
Binary dump of original server response, please notice C0 0C relative name references cause packet well under 512 byte limit.
Please this is old version of the patch, I post newer version with more general approach down below.
The text was updated successfully, but these errors were encountered: