#include "resolved-dns-domain.h"
#include "resolved-dns-packet.h"
-int dns_packet_new(DnsPacket **ret, size_t mtu) {
+int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
DnsPacket *p;
size_t a;
p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
p->allocated = a;
+ p->protocol = protocol;
p->n_ref = 1;
*ret = p;
return 0;
}
-int dns_packet_new_query(DnsPacket **ret, size_t mtu) {
+int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
DnsPacket *p;
DnsPacketHeader *h;
int r;
assert(ret);
- r = dns_packet_new(&p, mtu);
+ r = dns_packet_new(&p, protocol, mtu);
if (r < 0)
return r;
h = DNS_PACKET_HEADER(p);
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0));
+
+ if (protocol == DNS_PROTOCOL_DNS)
+ h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 1, 0, 0, 0, 0)); /* ask for recursion */
+ else
+ h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0));
*ret = p;
return 0;
assert(p);
- if (p->rrs)
- dns_resource_record_freev(p->rrs, DNS_PACKET_RRCOUNT(p));
+ dns_question_unref(p->question);
+ dns_answer_unref(p->answer);
while ((s = hashmap_steal_first_key(p->names)))
free(s);
hashmap_free(p->names);
- free(p->data);
+ free(p->_data);
free(p);
}
if (p->size + add > a)
return -EMSGSIZE;
- if (p->data) {
+ if (p->_data) {
void *d;
- d = realloc(p->data, a);
+ d = realloc(p->_data, a);
if (!d)
return -ENOMEM;
- p->data = d;
+ p->_data = d;
} else {
- p->data = malloc(a);
- if (!p->data)
+ p->_data = malloc(a);
+ if (!p->_data)
return -ENOMEM;
- memcpy(p->data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
- memzero((uint8_t*) p->data + p->size, a - p->size);
+ memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
+ memzero((uint8_t*) p->_data + p->size, a - p->size);
}
p->allocated = a;
saved_size = p->size;
- r = dns_packet_append_name(p, k->name, NULL);
+ r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), NULL);
if (r < 0)
goto fail;
return r;
}
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey *ret, size_t *start) {
- _cleanup_(dns_resource_key_free) DnsResourceKey k = {};
+int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
+ _cleanup_free_ char *name = NULL;
+ uint16_t class, type;
+ DnsResourceKey *key;
size_t saved_rindex;
int r;
saved_rindex = p->rindex;
- r = dns_packet_read_name(p, &k.name, NULL);
+ r = dns_packet_read_name(p, &name, NULL);
if (r < 0)
goto fail;
- r = dns_packet_read_uint16(p, &k.type, NULL);
+ r = dns_packet_read_uint16(p, &type, NULL);
if (r < 0)
goto fail;
- r = dns_packet_read_uint16(p, &k.class, NULL);
+ r = dns_packet_read_uint16(p, &class, NULL);
if (r < 0)
goto fail;
- *ret = k;
- zero(k);
+ key = dns_resource_key_new_consume(class, type, name);
+ if (!key) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ name = NULL;
+ *ret = key;
if (start)
*start = saved_rindex;
}
int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr;
+ _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
+ _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
size_t saved_rindex, offset;
uint16_t rdlength;
const void *d;
assert(p);
assert(ret);
- rr = dns_resource_record_new();
- if (!rr)
- return -ENOMEM;
-
saved_rindex = p->rindex;
- r = dns_packet_read_key(p, &rr->key, NULL);
+ r = dns_packet_read_key(p, &key, NULL);
if (r < 0)
goto fail;
+ rr = dns_resource_record_new(key);
+ if (!rr) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
r = dns_packet_read_uint32(p, &rr->ttl, NULL);
if (r < 0)
goto fail;
offset = p->rindex;
- switch (rr->key.type) {
+ switch (rr->key->type) {
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
memcpy(&rr->aaaa.in6_addr, d, sizeof(struct in6_addr));
break;
+ case DNS_TYPE_SOA:
+ r = dns_packet_read_name(p, &rr->soa.mname, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_name(p, &rr->soa.rname, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
+ if (r < 0)
+ goto fail;
+
+ r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
+ break;
+
default:
r = dns_packet_read(p, rdlength, &d, NULL);
if (r < 0)
return r;
}
-int dns_packet_skip_question(DnsPacket *p) {
- unsigned i, n;
+int dns_packet_extract(DnsPacket *p) {
+ _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
+ _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+ size_t saved_rindex;
+ unsigned n, i;
int r;
- assert(p);
-
+ saved_rindex = p->rindex;
dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
n = DNS_PACKET_QDCOUNT(p);
- for (i = 0; i < n; i++) {
- _cleanup_(dns_resource_key_free) DnsResourceKey key = {};
+ if (n > 0) {
+ question = dns_question_new(n);
+ if (!question) {
+ r = -ENOMEM;
+ goto finish;
+ }
- r = dns_packet_read_key(p, &key, NULL);
- if (r < 0)
- return r;
- }
+ for (i = 0; i < n; i++) {
+ _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- return 0;
-}
+ r = dns_packet_read_key(p, &key, NULL);
+ if (r < 0)
+ goto finish;
-int dns_packet_extract_rrs(DnsPacket *p) {
- DnsResourceRecord **rrs = NULL;
- size_t saved_rindex;
- unsigned n, added = 0;
- int r;
+ r = dns_question_add(question, key);
+ if (r < 0)
+ goto finish;
+ }
+ }
- if (p->rrs)
- return (int) DNS_PACKET_RRCOUNT(p);
+ n = DNS_PACKET_RRCOUNT(p);
+ if (n > 0) {
+ answer = dns_answer_new(n);
+ if (!answer) {
+ r = -ENOMEM;
+ goto finish;
+ }
- saved_rindex = p->rindex;
+ for (i = 0; i < n; i++) {
+ _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- r = dns_packet_skip_question(p);
- if (r < 0)
- goto finish;
+ r = dns_packet_read_rr(p, &rr, NULL);
+ if (r < 0)
+ goto finish;
- n = DNS_PACKET_RRCOUNT(p);
- if (n <= 0) {
- r = 0;
- goto finish;
+ r = dns_answer_add(answer, rr);
+ if (r < 0)
+ goto finish;
+ }
}
- rrs = new0(DnsResourceRecord*, n);
- if (!rrs) {
- r = -ENOMEM;
- goto finish;
- }
+ p->question = question;
+ question = NULL;
- for (added = 0; added < n; added++) {
- r = dns_packet_read_rr(p, &rrs[added], NULL);
- if (r < 0) {
- dns_resource_record_freev(rrs, added);
- goto finish;
- }
- }
+ p->answer = answer;
+ answer = NULL;
- p->rrs = rrs;
- r = (int) n;
+ r = 0;
finish:
p->rindex = saved_rindex;
[DNS_RCODE_BADTRUNC] = "BADTRUNC",
};
DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
+
+static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
+ [DNS_PROTOCOL_DNS] = "dns",
+ [DNS_PROTOCOL_MDNS] = "mdns",
+ [DNS_PROTOCOL_LLMNR] = "llmnr",
+};
+DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);