resolved-dns-packet.c revision a43a068a30f7a47aba39f8b48d5db0c4d39fd21d
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringint dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering /* round up to next page size */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* make sure we never allocate more than useful */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering p->opt_start = p->opt_size = (size_t) -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 0 /* opcode */,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen 0 /* rcode */));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen 0 /* opcode */,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 0 /* rd (ask for recursion) */,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen 0 /* rcode */));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 0 /* opcode */,
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering 0 /* rcode */));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* Always set the TC bit to 0 initially.
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * If there are multiple packets later, we'll update the bit shortly before sending.
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering dns_packet_set_flags(p, dnssec_checking_disabled, false);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic void dns_packet_free(DnsPacket *p) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering while ((s = hashmap_steal_first_key(p->names)))
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart PoetteringDnsPacket *dns_packet_unref(DnsPacket *p) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringint dns_packet_validate_reply(DnsPacket *p) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* RFC 6762, Section 18 */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringint dns_packet_validate_query(DnsPacket *p) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* RFC 6762, Section 18 */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memzero((uint8_t*) p->_data + p->size, a - p->size);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid dns_packet_truncate(DnsPacket *p, size_t sz) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringint dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringint dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringint dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversint dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
a6c616024db23fef34152c1432892824a07799ccLennart Poetteringint dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dns_packet_append_raw_string(p, s, strlen(s), start);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversint dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_extend(p, 1 + size, &d, start);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Append a label to a packet. Optionally, does this in DNSSEC
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers * canonical form, if this label is marked as a candidate for
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * it, and the canonical form logic is enabled for the
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_extend(p, 1 + l, (void**) &w, start);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers *(w++) = (uint8_t) l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Generate in canonical form, as defined by DNSSEC
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * RFC 4034, Section 6.2, i.e. all lower-case. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < l; i++)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Otherwise, just copy the string unaltered. This is
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * essential for DNS-SD, where the casing of labels
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers * matters and needs to be retained. */
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering const char *z = name;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (n > 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (n < 0x4000) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_label_unescape(&name, label, sizeof(label));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_append_label(p, label, r, canonical_candidate, &n);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poetteringint dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, true, NULL);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = dns_packet_append_uint16(p, k->type, NULL);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering r = dns_packet_append_uint16(p, k->class, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint8(p, window, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint8(p, length, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_blob(p, types, length, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering/* Append the OPT pseudo-RR described in RFC6891 */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poetteringint dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* we must never advertise supported packet size smaller than the legacy max */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* empty name */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* maximum udp packet that can be received */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = dns_packet_append_uint16(p, max_udp_size, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* extended RCODE and VERSION */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = dns_packet_append_uint16(p, 0, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* flags: DNSSEC OK (DO), see RFC3225 */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* RDLENGTH */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* If DO is on, also append RFC6975 Algorithm data */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint16(p, 0, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringint dns_packet_truncate_opt(DnsPacket *p) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (p->opt_start + p->opt_size != p->size)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering p->opt_start = p->opt_size = (size_t) -1;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringint dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering size_t saved_size, rdlength_offset, end, rdlength, rds;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_key(p, rr->key, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint32(p, rr->ttl, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Initially we write 0 here */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint16(p, 0, &rdlength_offset);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint16(p, rr->srv.port, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_name(p, rr->srv.name, true, false, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_string(p, rr->hinfo.os, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering case DNS_TYPE_SPF: /* exactly the same as TXT */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* RFC 6763, section 6.1 suggests to generate
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * single empty string for an empty array. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_raw_string(p, NULL, 0, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->loc.version, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->loc.size, NULL);
34a6778fb9d1065f3fbb8e2243b9f0f25d1d18f1Zbigniew Jędrzejewski-Szmek r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
f69157a66ffe413b4cf8bd79057487fc8921e78bThomas Hindoe Paaboel Andersen r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
bc9fd78c7bfc39881e19457e476393635f8b0442Lennart Poettering r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
6261f11fc3d0a8b63c5afa5313d96607a008b54eLennart Poettering r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt r = dns_packet_append_types(p, rr->nsec.types, NULL);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_types(p, rr->nsec3.types, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering /* Let's calculate the actual data size and update the field */
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering rdlength = p->size - rdlength_offset - sizeof(uint16_t);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = dns_packet_append_uint16(p, rdlength, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poetteringint dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringvoid dns_packet_rewind(DnsPacket *p, size_t idx) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const void *q;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_read(p, size, &src, &start);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const void *d;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen r = dns_packet_read(p, sizeof(uint8_t), &d, start);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const void *d;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering r = dns_packet_read(p, sizeof(uint16_t), &d, start);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringint dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const void *d;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = dns_packet_read(p, sizeof(uint32_t), &d, start);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const void *d;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (memchr(d, 0, c)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t saved_rindex, after_rindex = 0, jump_barrier;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* End of name */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (c <= 63) {
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering /* Literal label */
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering r = dns_packet_read(p, c, (const void**) &label, NULL);
r = -ENOMEM;
goto fail;
if (first)
first = false;
goto fail;
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;
if (dns_type_is_pseudo(n))
goto fail;
bit ++;
if (!found)
return -EBADMSG;
if (start)
fail:
goto fail;
r = -EBADMSG;
goto fail;
r = -EBADMSG;
goto fail;
if (start)
fail:
bool cache_flush = false;
assert(p);
goto fail;
goto fail;
goto fail;
cache_flush = true;
if (!key) {
r = -ENOMEM;
goto fail;
if (ret_cache_flush)
if (start)
fail:
int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) {
bool cache_flush;
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) {
DnsTxtItem *i;
return -ENOMEM;
DnsTxtItem *i;
const void *data;
return -ENOMEM;
last = i;
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;
r = -EBADMSG;
goto fail;
case DNS_TYPE_SSHFP:
goto fail;
goto fail;
NULL);
r = -EBADMSG;
goto fail;
case DNS_TYPE_DNSKEY:
goto fail;
goto fail;
goto fail;
NULL);
r = -EBADMSG;
goto fail;
case DNS_TYPE_RRSIG:
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
NULL);
r = -EBADMSG;
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;
if (size <= 0) {
r = -EBADMSG;
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;
case DNS_TYPE_TLSA:
goto fail;
goto fail;
goto fail;
NULL);
r = -EBADMSG;
goto fail;
case DNS_TYPE_OPENPGPKEY:
goto fail;
goto fail;
r = -EBADMSG;
goto fail;
if (ret_cache_flush)
if (start)
fail:
const uint8_t* p;
bool found_dau_dhu_n3u = false;
size_t l;
/* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in
found_dau_dhu_n3u = true;
if (p->extracted)
n = DNS_PACKET_QDCOUNT(p);
if (!question) {
r = -ENOMEM;
goto finish;
bool cache_flush;
goto finish;
if (cache_flush) {
r = -EBADMSG;
goto finish;
r = -EBADMSG;
goto finish;
goto finish;
n = DNS_PACKET_RRCOUNT(p);
bool bad_opt = false;
if (!answer) {
r = -ENOMEM;
goto finish;
bool cache_flush;
goto finish;
if (previous)
bool has_rfc6975;
bad_opt = true;
bad_opt = true;
bad_opt = true;
bad_opt = true;
if (has_rfc6975) {
bad_opt = true;
goto finish;
if (bad_opt)
p->extracted = true;
assert(p);
r = dns_packet_extract(p);