resolved-dns-packet.c revision f5430a3ef308f3a102899fcaf7fbece757082f2a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster This file is part of systemd.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Copyright 2014 Lennart Poettering
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster systemd is free software; you can redistribute it and/or modify it
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster under the terms of the GNU Lesser General Public License as published by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster the Free Software Foundation; either version 2.1 of the License, or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (at your option) any later version.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster systemd is distributed in the hope that it will be useful, but
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster WITHOUT ANY WARRANTY; without even the implied warranty of
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Lesser General Public License for more details.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster You should have received a copy of the GNU Lesser General Public License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster along with systemd; If not, see <http://www.gnu.org/licenses/>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterint dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* round up to next page size */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* make sure we never allocate more than useful */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterint dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster 0 /* opcode */,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster 0 /* rcode */));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster 0 /* opcode */,
*ret = p;
return NULL;
p->n_ref++;
assert(p);
free(s);
free(p);
return NULL;
dns_packet_free(p);
p->n_ref--;
return NULL;
assert(p);
return -EBADMSG;
return -EBADMSG;
assert(p);
r = dns_packet_validate(p);
if (DNS_PACKET_OPCODE(p) != 0)
return -EBADMSG;
switch (p->protocol) {
case DNS_PROTOCOL_LLMNR:
return -EBADMSG;
assert(p);
r = dns_packet_validate(p);
if (DNS_PACKET_QR(p) != 0)
if (DNS_PACKET_OPCODE(p) != 0)
return -EBADMSG;
if (DNS_PACKET_TC(p))
return -EBADMSG;
switch (p->protocol) {
case DNS_PROTOCOL_LLMNR:
return -EBADMSG;
if (DNS_PACKET_ANCOUNT(p) > 0)
return -EBADMSG;
if (DNS_PACKET_NSCOUNT(p) > 0)
return -EBADMSG;
assert(p);
size_t a;
if (a > DNS_PACKET_SIZE_MAX)
a = DNS_PACKET_SIZE_MAX;
return -EMSGSIZE;
if (p->_data) {
return -ENOMEM;
p->_data = d;
if (!p->_data)
return -ENOMEM;
p->allocated = a;
if (start)
if (ret)
Iterator i;
assert(p);
free(s);
assert(p);
memcpy(q, d, l);
assert(p);
((uint8_t*) d)[0] = v;
assert(p);
unaligned_write_be16(d, v);
assert(p);
unaligned_write_be32(d, v);
size_t l;
assert(p);
assert(s);
l = strlen(s);
return -E2BIG;
assert(p);
assert(d);
if (l > DNS_LABEL_MAX)
return -E2BIG;
assert(p);
while (*name) {
size_t n = 0;
if (allow_compression)
goto fail;
goto done;
r = -ENOMEM;
goto fail;
goto fail;
goto fail;
goto fail;
if (allow_compression) {
goto fail;
goto fail;
s = NULL;
done:
if (start)
fail:
assert(p);
assert(k);
goto fail;
goto fail;
goto fail;
if (start)
fail:
static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, uint8_t *types, size_t *start) {
assert(p);
if (length == 0)
goto fail;
goto fail;
goto fail;
if (start)
fail:
Iterator i;
assert(p);
goto fail;
if (len > 0) {
len = 0;
len ++;
goto fail;
if (start)
fail:
assert(p);
goto fail;
goto fail;
goto fail;
case DNS_TYPE_SRV:
goto fail;
goto fail;
goto fail;
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
case DNS_TYPE_CNAME:
case DNS_TYPE_DNAME:
case DNS_TYPE_HINFO:
goto fail;
case DNS_TYPE_TXT: {
goto fail;
goto fail;
case DNS_TYPE_A:
case DNS_TYPE_AAAA:
case DNS_TYPE_SOA:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
case DNS_TYPE_MX:
goto fail;
case DNS_TYPE_LOC:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
case DNS_TYPE_DS:
goto fail;
goto fail;
goto fail;
case DNS_TYPE_SSHFP:
goto fail;
goto fail;
case DNS_TYPE_DNSKEY:
goto fail;
goto fail;
goto fail;
case DNS_TYPE_RRSIG:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
case DNS_TYPE_NSEC:
goto fail;
goto fail;
case DNS_TYPE_NSEC3:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
r = ENOSPC;
goto fail;
goto fail;
if (start)
fail:
assert(p);
return -EMSGSIZE;
if (ret)
if (start)
assert(p);
assert(p);
assert(d);
static int dns_packet_read_memdup(
const void *src;
assert(p);
if (size <= 0)
void *copy;
if (!copy)
return -ENOMEM;
if (ret_size)
if (ret_start)
assert(p);
assert(p);
assert(p);
uint8_t c;
assert(p);
goto fail;
goto fail;
if (memchr(d, 0, c)) {
r = -EBADMSG;
goto fail;
t = strndup(d, c);
r = -ENOMEM;
goto fail;
if (!utf8_is_valid(t)) {
free(t);
r = -EBADMSG;
goto fail;
*ret = t;
if (start)
fail:
bool first = true;
assert(p);
uint8_t c, d;
goto fail;
const char *label;
goto fail;
goto fail;
r = -ENOMEM;
goto fail;
if (!first)
first = false;
goto fail;
r = -EBADMSG;
goto fail;
if (after_rindex == 0)
r = -EBADMSG;
goto fail;
r = -ENOMEM;
goto fail;
ret[n] = 0;
if (after_rindex != 0)
if (start)
fail:
bool found = false;
assert(p);
goto fail;
goto fail;
goto fail;
return -EBADMSG;
goto fail;
for (i = 0; i < length; i++) {
if (!bitmap[i]) {
found = false;
found = true;
while (bitmask) {
uint16_t n;
goto fail;
bit ++;
if (!found)
return -EBADMSG;
if (start)
fail:
assert(p);
goto fail;
goto fail;
goto fail;
if (!key) {
r = -ENOMEM;
goto fail;
if (start)
fail:
return -EBADMSG;
assert(p);
goto fail;
r = -EBADMSG;
goto fail;
if (!rr) {
r = -ENOMEM;
goto fail;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
case DNS_TYPE_SRV:
goto fail;
goto fail;
goto fail;
case DNS_TYPE_PTR:
case DNS_TYPE_NS:
case DNS_TYPE_CNAME:
case DNS_TYPE_DNAME:
case DNS_TYPE_HINFO:
goto fail;
case DNS_TYPE_TXT:
if (rdlength <= 0) {
goto fail;
goto fail;
goto fail;
case DNS_TYPE_A:
case DNS_TYPE_AAAA:
case DNS_TYPE_SOA:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
case DNS_TYPE_MX:
goto fail;
case DNS_TYPE_LOC: {
uint8_t t;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
goto fail;
goto fail;
goto fail;
goto unparseable;
case DNS_TYPE_DS:
goto fail;
goto fail;
goto fail;
NULL);
goto fail;
case DNS_TYPE_SSHFP:
goto fail;
goto fail;
NULL);
case DNS_TYPE_DNSKEY: {
goto fail;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
goto fail;
NULL);
case DNS_TYPE_RRSIG:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
NULL);
case DNS_TYPE_NSEC:
goto fail;
goto fail;
case DNS_TYPE_NSEC3: {
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
goto fail;
goto fail;
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
if (start)
fail:
if (p->extracted)
n = DNS_PACKET_QDCOUNT(p);
if (!question) {
r = -ENOMEM;
goto finish;
goto finish;
goto finish;
n = DNS_PACKET_RRCOUNT(p);
if (!answer) {
r = -ENOMEM;
goto finish;
goto finish;
goto finish;
p->extracted = true;