summaryrefslogtreecommitdiff
path: root/src/resolve
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-12-09 17:43:24 +0100
committerLennart Poettering <lennart@poettering.net>2015-12-10 11:35:52 +0100
commitd75acfb059ece4512278b8820a9103664996f1e5 (patch)
tree6c030e51969b64b87d991eed9a799817651750a1 /src/resolve
parentc296dd2eea308e9ef73eb81f31e9eeaa32c30895 (diff)
resolved: when parsing DNS packets, handle OPT RR specially
As soon as we encounter the OPT RR while parsing, store it in a special field in the DnsPacket structure. That way, we won't be confused if we iterate through RRs, and can check that there's really only one of these RRs around.
Diffstat (limited to 'src/resolve')
-rw-r--r--src/resolve/resolved-dns-packet.c26
-rw-r--r--src/resolve/resolved-dns-packet.h1
-rw-r--r--src/resolve/resolved-dns-rr.h2
3 files changed, 21 insertions, 8 deletions
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index f753b3522f..d20814651e 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -153,6 +153,7 @@ static void dns_packet_free(DnsPacket *p) {
dns_question_unref(p->question);
dns_answer_unref(p->answer);
+ dns_resource_record_unref(p->opt);
while ((s = hashmap_steal_first_key(p->names)))
free(s);
@@ -209,6 +210,7 @@ int dns_packet_validate_reply(DnsPacket *p) {
return -EBADMSG;
switch (p->protocol) {
+
case DNS_PROTOCOL_LLMNR:
/* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
if (DNS_PACKET_QDCOUNT(p) != 1)
@@ -249,6 +251,7 @@ int dns_packet_validate_query(DnsPacket *p) {
return -EBADMSG;
switch (p->protocol) {
+
case DNS_PROTOCOL_LLMNR:
/* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
if (DNS_PACKET_QDCOUNT(p) != 1)
@@ -963,6 +966,7 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
goto fail;
break;
+
case DNS_TYPE_NSEC3:
r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
if (r < 0)
@@ -997,6 +1001,8 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
goto fail;
break;
+
+ case DNS_TYPE_OPT:
case _DNS_TYPE_INVALID: /* unparseable */
default:
@@ -1568,10 +1574,6 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
break;
- case DNS_TYPE_OPT: /* we only care about the header */
- r = 0;
- break;
-
case DNS_TYPE_HINFO:
r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
if (r < 0)
@@ -1749,6 +1751,7 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
}
break;
+
case DNS_TYPE_SSHFP:
r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
if (r < 0)
@@ -1911,6 +1914,8 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
break;
}
+
+ case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
default:
unparseable:
r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
@@ -1986,9 +1991,16 @@ int dns_packet_extract(DnsPacket *p) {
if (r < 0)
goto finish;
- r = dns_answer_add(answer, rr, p->ifindex);
- if (r < 0)
- goto finish;
+ if (rr->key->type == DNS_TYPE_OPT) {
+ if (p->opt)
+ return -EBADMSG;
+
+ p->opt = dns_resource_record_ref(rr);
+ } else {
+ r = dns_answer_add(answer, rr, p->ifindex);
+ if (r < 0)
+ goto finish;
+ }
}
}
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index 3d84cb622b..b0b8600232 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -80,6 +80,7 @@ struct DnsPacket {
/* Parsed data */
DnsQuestion *question;
DnsAnswer *answer;
+ DnsResourceRecord *opt;
/* Packet reception metadata */
int ifindex;
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
index 5c2306ba96..941f3cfe67 100644
--- a/src/resolve/resolved-dns-rr.h
+++ b/src/resolve/resolved-dns-rr.h
@@ -114,7 +114,7 @@ struct DnsResourceRecord {
struct {
void *data;
size_t size;
- } generic;
+ } generic, opt;
struct {
uint16_t priority;