| File: | build-scan/../src/resolve/resolved-dns-packet.c |
| Warning: | line 580, column 9 Potential leak of memory pointed to by 's' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | /*** | |||
| 3 | ***/ | |||
| 4 | ||||
| 5 | #if HAVE_GCRYPT1 | |||
| 6 | #include <gcrypt.h> | |||
| 7 | #endif | |||
| 8 | ||||
| 9 | #include "alloc-util.h" | |||
| 10 | #include "dns-domain.h" | |||
| 11 | #include "resolved-dns-packet.h" | |||
| 12 | #include "string-table.h" | |||
| 13 | #include "strv.h" | |||
| 14 | #include "unaligned.h" | |||
| 15 | #include "utf8.h" | |||
| 16 | #include "util.h" | |||
| 17 | ||||
| 18 | #define EDNS0_OPT_DO(1<<15) (1<<15) | |||
| 19 | ||||
| 20 | assert_cc(DNS_PACKET_SIZE_START > DNS_PACKET_HEADER_SIZE)GCC diagnostic push
; GCC diagnostic ignored "-Wdeclaration-after-statement" ; struct _assert_struct_16 { char x[(512u > sizeof(DnsPacketHeader )) ? 0 : -1]; }; GCC diagnostic pop | |||
| 21 | ||||
| 22 | typedef struct DnsPacketRewinder { | |||
| 23 | DnsPacket *packet; | |||
| 24 | size_t saved_rindex; | |||
| 25 | } DnsPacketRewinder; | |||
| 26 | ||||
| 27 | static void rewind_dns_packet(DnsPacketRewinder *rewinder) { | |||
| 28 | if (rewinder->packet) | |||
| 29 | dns_packet_rewind(rewinder->packet, rewinder->saved_rindex); | |||
| 30 | } | |||
| 31 | ||||
| 32 | #define INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while (0) | |||
| 33 | #define CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0) do { rewinder.packet = NULL((void*)0); } while (0) | |||
| 34 | ||||
| 35 | int dns_packet_new( | |||
| 36 | DnsPacket **ret, | |||
| 37 | DnsProtocol protocol, | |||
| 38 | size_t min_alloc_dsize, | |||
| 39 | size_t max_size) { | |||
| 40 | ||||
| 41 | DnsPacket *p; | |||
| 42 | size_t a; | |||
| 43 | ||||
| 44 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-packet.c" , 44, __PRETTY_FUNCTION__); } while (0); | |||
| 45 | assert(max_size >= DNS_PACKET_HEADER_SIZE)do { if ((__builtin_expect(!!(!(max_size >= sizeof(DnsPacketHeader ))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("max_size >= DNS_PACKET_HEADER_SIZE" ), "../src/resolve/resolved-dns-packet.c", 45, __PRETTY_FUNCTION__ ); } while (0); | |||
| 46 | ||||
| 47 | if (max_size > DNS_PACKET_SIZE_MAX0xFFFFu) | |||
| 48 | max_size = DNS_PACKET_SIZE_MAX0xFFFFu; | |||
| 49 | ||||
| 50 | /* The caller may not check what is going to be truly allocated, so do not allow to | |||
| 51 | * allocate a DNS packet bigger than DNS_PACKET_SIZE_MAX. | |||
| 52 | */ | |||
| 53 | if (min_alloc_dsize > DNS_PACKET_SIZE_MAX0xFFFFu) { | |||
| 54 | log_error("Requested packet data size too big: %zu", min_alloc_dsize)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-dns-packet.c", 54, __func__, "Requested packet data size too big: %zu" , min_alloc_dsize) : -abs(_e); }); | |||
| 55 | return -EFBIG27; | |||
| 56 | } | |||
| 57 | ||||
| 58 | /* When dns_packet_new() is called with min_alloc_dsize == 0, allocate more than the | |||
| 59 | * absolute minimum (which is the dns packet header size), to avoid | |||
| 60 | * resizing immediately again after appending the first data to the packet. | |||
| 61 | */ | |||
| 62 | if (min_alloc_dsize < DNS_PACKET_HEADER_SIZEsizeof(DnsPacketHeader)) | |||
| 63 | a = DNS_PACKET_SIZE_START512u; | |||
| 64 | else | |||
| 65 | a = min_alloc_dsize; | |||
| 66 | ||||
| 67 | /* round up to next page size */ | |||
| 68 | a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a)ALIGN_TO(((((sizeof(DnsPacket)) + 7) & ~7) + a), page_size ()) - ALIGN(sizeof(DnsPacket))(((sizeof(DnsPacket)) + 7) & ~7); | |||
| 69 | ||||
| 70 | /* make sure we never allocate more than useful */ | |||
| 71 | if (a > max_size) | |||
| 72 | a = max_size; | |||
| 73 | ||||
| 74 | p = malloc0(ALIGN(sizeof(DnsPacket)) + a)(calloc(1, ((((sizeof(DnsPacket)) + 7) & ~7) + a))); | |||
| 75 | if (!p) | |||
| 76 | return -ENOMEM12; | |||
| 77 | ||||
| 78 | p->size = p->rindex = DNS_PACKET_HEADER_SIZEsizeof(DnsPacketHeader); | |||
| 79 | p->allocated = a; | |||
| 80 | p->max_size = max_size; | |||
| 81 | p->protocol = protocol; | |||
| 82 | p->opt_start = p->opt_size = (size_t) -1; | |||
| 83 | p->n_ref = 1; | |||
| 84 | ||||
| 85 | *ret = p; | |||
| 86 | ||||
| 87 | return 0; | |||
| 88 | } | |||
| 89 | ||||
| 90 | void dns_packet_set_flags(DnsPacket *p, bool_Bool dnssec_checking_disabled, bool_Bool truncated) { | |||
| 91 | ||||
| 92 | DnsPacketHeader *h; | |||
| 93 | ||||
| 94 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 94, __PRETTY_FUNCTION__); } while (0); | |||
| 95 | ||||
| 96 | h = DNS_PACKET_HEADER(p)((DnsPacketHeader*) DNS_PACKET_DATA(p)); | |||
| 97 | ||||
| 98 | switch(p->protocol) { | |||
| 99 | case DNS_PROTOCOL_LLMNR: | |||
| 100 | assert(!truncated)do { if ((__builtin_expect(!!(!(!truncated)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!truncated"), "../src/resolve/resolved-dns-packet.c" , 100, __PRETTY_FUNCTION__); } while (0); | |||
| 101 | ||||
| 102 | h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 103 | 0 /* opcode */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 104 | 0 /* c */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 105 | 0 /* tc */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 106 | 0 /* t */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 107 | 0 /* ra */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 108 | 0 /* ad */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 109 | 0 /* cd */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 110 | 0 /* rcode */)(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(0) << 4) | ((uint16_t) ((0) & 15)))); | |||
| 111 | break; | |||
| 112 | ||||
| 113 | case DNS_PROTOCOL_MDNS: | |||
| 114 | h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 115 | 0 /* opcode */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 116 | 0 /* aa */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 117 | truncated /* tc */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 118 | 0 /* rd (ask for recursion) */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 119 | 0 /* ra */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 120 | 0 /* ad */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 121 | 0 /* cd */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15))) | |||
| 122 | 0 /* rcode */)(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(truncated ) << 9) | ((uint16_t) !!(0) << 8) | ((uint16_t) ! !(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t ) !!(0) << 4) | ((uint16_t) ((0) & 15)))); | |||
| 123 | break; | |||
| 124 | ||||
| 125 | default: | |||
| 126 | assert(!truncated)do { if ((__builtin_expect(!!(!(!truncated)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!truncated"), "../src/resolve/resolved-dns-packet.c" , 126, __PRETTY_FUNCTION__); } while (0); | |||
| 127 | ||||
| 128 | h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 129 | 0 /* opcode */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 130 | 0 /* aa */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 131 | 0 /* tc */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 132 | 1 /* rd (ask for recursion) */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 133 | 0 /* ra */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 134 | 0 /* ad */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 135 | dnssec_checking_disabled /* cd */,(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15))) | |||
| 136 | 0 /* rcode */)(((uint16_t) !!(0) << 15) | ((uint16_t) ((0) & 15) << 11) | ((uint16_t) !!(0) << 10) | ((uint16_t) !!(0) << 9) | ((uint16_t) !!(1) << 8) | ((uint16_t) !!(0) << 7) | ((uint16_t) !!(0) << 5) | ((uint16_t) !!(dnssec_checking_disabled ) << 4) | ((uint16_t) ((0) & 15)))); | |||
| 137 | } | |||
| 138 | } | |||
| 139 | ||||
| 140 | int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc_dsize, bool_Bool dnssec_checking_disabled) { | |||
| 141 | DnsPacket *p; | |||
| 142 | int r; | |||
| 143 | ||||
| 144 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-packet.c" , 144, __PRETTY_FUNCTION__); } while (0); | |||
| 145 | ||||
| 146 | r = dns_packet_new(&p, protocol, min_alloc_dsize, DNS_PACKET_SIZE_MAX0xFFFFu); | |||
| 147 | if (r < 0) | |||
| 148 | return r; | |||
| 149 | ||||
| 150 | /* Always set the TC bit to 0 initially. | |||
| 151 | * If there are multiple packets later, we'll update the bit shortly before sending. | |||
| 152 | */ | |||
| 153 | dns_packet_set_flags(p, dnssec_checking_disabled, false0); | |||
| 154 | ||||
| 155 | *ret = p; | |||
| 156 | return 0; | |||
| 157 | } | |||
| 158 | ||||
| 159 | DnsPacket *dns_packet_ref(DnsPacket *p) { | |||
| 160 | ||||
| 161 | if (!p) | |||
| 162 | return NULL((void*)0); | |||
| 163 | ||||
| 164 | assert(!p->on_stack)do { if ((__builtin_expect(!!(!(!p->on_stack)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!p->on_stack"), "../src/resolve/resolved-dns-packet.c" , 164, __PRETTY_FUNCTION__); } while (0); | |||
| 165 | ||||
| 166 | assert(p->n_ref > 0)do { if ((__builtin_expect(!!(!(p->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p->n_ref > 0"), "../src/resolve/resolved-dns-packet.c" , 166, __PRETTY_FUNCTION__); } while (0); | |||
| 167 | p->n_ref++; | |||
| 168 | return p; | |||
| 169 | } | |||
| 170 | ||||
| 171 | static void dns_packet_free(DnsPacket *p) { | |||
| 172 | char *s; | |||
| 173 | ||||
| 174 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 174, __PRETTY_FUNCTION__); } while (0); | |||
| 175 | ||||
| 176 | dns_question_unref(p->question); | |||
| 177 | dns_answer_unref(p->answer); | |||
| 178 | dns_resource_record_unref(p->opt); | |||
| 179 | ||||
| 180 | while ((s = hashmap_steal_first_key(p->names))) | |||
| 181 | free(s); | |||
| 182 | hashmap_free(p->names); | |||
| 183 | ||||
| 184 | free(p->_data); | |||
| 185 | ||||
| 186 | if (!p->on_stack) | |||
| 187 | free(p); | |||
| 188 | } | |||
| 189 | ||||
| 190 | DnsPacket *dns_packet_unref(DnsPacket *p) { | |||
| 191 | if (!p) | |||
| 192 | return NULL((void*)0); | |||
| 193 | ||||
| 194 | assert(p->n_ref > 0)do { if ((__builtin_expect(!!(!(p->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p->n_ref > 0"), "../src/resolve/resolved-dns-packet.c" , 194, __PRETTY_FUNCTION__); } while (0); | |||
| 195 | ||||
| 196 | dns_packet_unref(p->more); | |||
| 197 | ||||
| 198 | if (p->n_ref == 1) | |||
| 199 | dns_packet_free(p); | |||
| 200 | else | |||
| 201 | p->n_ref--; | |||
| 202 | ||||
| 203 | return NULL((void*)0); | |||
| 204 | } | |||
| 205 | ||||
| 206 | int dns_packet_validate(DnsPacket *p) { | |||
| 207 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 207, __PRETTY_FUNCTION__); } while (0); | |||
| 208 | ||||
| 209 | if (p->size < DNS_PACKET_HEADER_SIZEsizeof(DnsPacketHeader)) | |||
| 210 | return -EBADMSG74; | |||
| 211 | ||||
| 212 | if (p->size > DNS_PACKET_SIZE_MAX0xFFFFu) | |||
| 213 | return -EBADMSG74; | |||
| 214 | ||||
| 215 | return 1; | |||
| 216 | } | |||
| 217 | ||||
| 218 | int dns_packet_validate_reply(DnsPacket *p) { | |||
| 219 | int r; | |||
| 220 | ||||
| 221 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 221, __PRETTY_FUNCTION__); } while (0); | |||
| 222 | ||||
| 223 | r = dns_packet_validate(p); | |||
| 224 | if (r < 0) | |||
| 225 | return r; | |||
| 226 | ||||
| 227 | if (DNS_PACKET_QR(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 15) & 1) != 1) | |||
| 228 | return 0; | |||
| 229 | ||||
| 230 | if (DNS_PACKET_OPCODE(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 11) & 15) != 0) | |||
| 231 | return -EBADMSG74; | |||
| 232 | ||||
| 233 | switch (p->protocol) { | |||
| 234 | ||||
| 235 | case DNS_PROTOCOL_LLMNR: | |||
| 236 | /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */ | |||
| 237 | if (DNS_PACKET_QDCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->qdcount) != 1) | |||
| 238 | return -EBADMSG74; | |||
| 239 | ||||
| 240 | break; | |||
| 241 | ||||
| 242 | case DNS_PROTOCOL_MDNS: | |||
| 243 | /* RFC 6762, Section 18 */ | |||
| 244 | if (DNS_PACKET_RCODE(p) != 0) | |||
| 245 | return -EBADMSG74; | |||
| 246 | ||||
| 247 | break; | |||
| 248 | ||||
| 249 | default: | |||
| 250 | break; | |||
| 251 | } | |||
| 252 | ||||
| 253 | return 1; | |||
| 254 | } | |||
| 255 | ||||
| 256 | int dns_packet_validate_query(DnsPacket *p) { | |||
| 257 | int r; | |||
| 258 | ||||
| 259 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 259, __PRETTY_FUNCTION__); } while (0); | |||
| 260 | ||||
| 261 | r = dns_packet_validate(p); | |||
| 262 | if (r < 0) | |||
| 263 | return r; | |||
| 264 | ||||
| 265 | if (DNS_PACKET_QR(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 15) & 1) != 0) | |||
| 266 | return 0; | |||
| 267 | ||||
| 268 | if (DNS_PACKET_OPCODE(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 11) & 15) != 0) | |||
| 269 | return -EBADMSG74; | |||
| 270 | ||||
| 271 | if (DNS_PACKET_TC(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 9) & 1)) | |||
| 272 | return -EBADMSG74; | |||
| 273 | ||||
| 274 | switch (p->protocol) { | |||
| 275 | ||||
| 276 | case DNS_PROTOCOL_LLMNR: | |||
| 277 | case DNS_PROTOCOL_DNS: | |||
| 278 | /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */ | |||
| 279 | if (DNS_PACKET_QDCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->qdcount) != 1) | |||
| 280 | return -EBADMSG74; | |||
| 281 | ||||
| 282 | /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */ | |||
| 283 | if (DNS_PACKET_ANCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->ancount) > 0) | |||
| 284 | return -EBADMSG74; | |||
| 285 | ||||
| 286 | /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */ | |||
| 287 | if (DNS_PACKET_NSCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->nscount) > 0) | |||
| 288 | return -EBADMSG74; | |||
| 289 | ||||
| 290 | break; | |||
| 291 | ||||
| 292 | case DNS_PROTOCOL_MDNS: | |||
| 293 | /* RFC 6762, Section 18 */ | |||
| 294 | if (DNS_PACKET_AA(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 10) & 1) != 0 || | |||
| 295 | DNS_PACKET_RD(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 8) & 1) != 0 || | |||
| 296 | DNS_PACKET_RA(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 7) & 1) != 0 || | |||
| 297 | DNS_PACKET_AD(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 5) & 1) != 0 || | |||
| 298 | DNS_PACKET_CD(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 4) & 1) != 0 || | |||
| 299 | DNS_PACKET_RCODE(p) != 0) | |||
| 300 | return -EBADMSG74; | |||
| 301 | ||||
| 302 | break; | |||
| 303 | ||||
| 304 | default: | |||
| 305 | break; | |||
| 306 | } | |||
| 307 | ||||
| 308 | return 1; | |||
| 309 | } | |||
| 310 | ||||
| 311 | static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) { | |||
| 312 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 312, __PRETTY_FUNCTION__); } while (0); | |||
| 313 | ||||
| 314 | if (p->size + add > p->allocated) { | |||
| 315 | size_t a, ms; | |||
| 316 | ||||
| 317 | a = PAGE_ALIGN((p->size + add) * 2)ALIGN_TO(((p->size + add) * 2), page_size()); | |||
| 318 | ||||
| 319 | ms = dns_packet_size_max(p); | |||
| 320 | if (a > ms) | |||
| 321 | a = ms; | |||
| 322 | ||||
| 323 | if (p->size + add > a) | |||
| 324 | return -EMSGSIZE90; | |||
| 325 | ||||
| 326 | if (p->_data) { | |||
| 327 | void *d; | |||
| 328 | ||||
| 329 | d = realloc(p->_data, a); | |||
| 330 | if (!d) | |||
| 331 | return -ENOMEM12; | |||
| 332 | ||||
| 333 | p->_data = d; | |||
| 334 | } else { | |||
| 335 | p->_data = malloc(a); | |||
| 336 | if (!p->_data) | |||
| 337 | return -ENOMEM12; | |||
| 338 | ||||
| 339 | memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket))(((sizeof(DnsPacket)) + 7) & ~7), p->size); | |||
| 340 | memzero((uint8_t*) p->_data + p->size, a - p->size)({ size_t _l_ = (a - p->size); void *_x_ = ((uint8_t*) p-> _data + p->size); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }); | |||
| 341 | } | |||
| 342 | ||||
| 343 | p->allocated = a; | |||
| 344 | } | |||
| 345 | ||||
| 346 | if (start) | |||
| 347 | *start = p->size; | |||
| 348 | ||||
| 349 | if (ret) | |||
| 350 | *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size; | |||
| 351 | ||||
| 352 | p->size += add; | |||
| 353 | return 0; | |||
| 354 | } | |||
| 355 | ||||
| 356 | void dns_packet_truncate(DnsPacket *p, size_t sz) { | |||
| 357 | Iterator i; | |||
| 358 | char *s; | |||
| 359 | void *n; | |||
| 360 | ||||
| 361 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 361, __PRETTY_FUNCTION__); } while (0); | |||
| 362 | ||||
| 363 | if (p->size <= sz) | |||
| 364 | return; | |||
| 365 | ||||
| 366 | HASHMAP_FOREACH_KEY(n, s, p->names, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((p->names), & (i), (void**)&(n), (const void**) &(s)); ) { | |||
| 367 | ||||
| 368 | if (PTR_TO_SIZE(n)((size_t) ((uintptr_t) (n))) < sz) | |||
| 369 | continue; | |||
| 370 | ||||
| 371 | hashmap_remove(p->names, s); | |||
| 372 | free(s); | |||
| 373 | } | |||
| 374 | ||||
| 375 | p->size = sz; | |||
| 376 | } | |||
| 377 | ||||
| 378 | int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) { | |||
| 379 | void *q; | |||
| 380 | int r; | |||
| 381 | ||||
| 382 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 382, __PRETTY_FUNCTION__); } while (0); | |||
| 383 | ||||
| 384 | r = dns_packet_extend(p, l, &q, start); | |||
| 385 | if (r < 0) | |||
| 386 | return r; | |||
| 387 | ||||
| 388 | memcpy(q, d, l); | |||
| 389 | return 0; | |||
| 390 | } | |||
| 391 | ||||
| 392 | int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) { | |||
| 393 | void *d; | |||
| 394 | int r; | |||
| 395 | ||||
| 396 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 396, __PRETTY_FUNCTION__); } while (0); | |||
| 397 | ||||
| 398 | r = dns_packet_extend(p, sizeof(uint8_t), &d, start); | |||
| 399 | if (r < 0) | |||
| 400 | return r; | |||
| 401 | ||||
| 402 | ((uint8_t*) d)[0] = v; | |||
| 403 | ||||
| 404 | return 0; | |||
| 405 | } | |||
| 406 | ||||
| 407 | int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) { | |||
| 408 | void *d; | |||
| 409 | int r; | |||
| 410 | ||||
| 411 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 411, __PRETTY_FUNCTION__); } while (0); | |||
| 412 | ||||
| 413 | r = dns_packet_extend(p, sizeof(uint16_t), &d, start); | |||
| 414 | if (r < 0) | |||
| 415 | return r; | |||
| 416 | ||||
| 417 | unaligned_write_be16(d, v); | |||
| 418 | ||||
| 419 | return 0; | |||
| 420 | } | |||
| 421 | ||||
| 422 | int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) { | |||
| 423 | void *d; | |||
| 424 | int r; | |||
| 425 | ||||
| 426 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 426, __PRETTY_FUNCTION__); } while (0); | |||
| 427 | ||||
| 428 | r = dns_packet_extend(p, sizeof(uint32_t), &d, start); | |||
| 429 | if (r < 0) | |||
| 430 | return r; | |||
| 431 | ||||
| 432 | unaligned_write_be32(d, v); | |||
| 433 | ||||
| 434 | return 0; | |||
| 435 | } | |||
| 436 | ||||
| 437 | int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) { | |||
| 438 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 438, __PRETTY_FUNCTION__); } while (0); | |||
| 439 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/resolve/resolved-dns-packet.c" , 439, __PRETTY_FUNCTION__); } while (0); | |||
| 440 | ||||
| 441 | return dns_packet_append_raw_string(p, s, strlen(s), start); | |||
| 442 | } | |||
| 443 | ||||
| 444 | int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) { | |||
| 445 | void *d; | |||
| 446 | int r; | |||
| 447 | ||||
| 448 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 448, __PRETTY_FUNCTION__); } while (0); | |||
| 449 | assert(s || size == 0)do { if ((__builtin_expect(!!(!(s || size == 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s || size == 0"), "../src/resolve/resolved-dns-packet.c" , 449, __PRETTY_FUNCTION__); } while (0); | |||
| 450 | ||||
| 451 | if (size > 255) | |||
| 452 | return -E2BIG7; | |||
| 453 | ||||
| 454 | r = dns_packet_extend(p, 1 + size, &d, start); | |||
| 455 | if (r < 0) | |||
| 456 | return r; | |||
| 457 | ||||
| 458 | ((uint8_t*) d)[0] = (uint8_t) size; | |||
| 459 | ||||
| 460 | memcpy_safe(((uint8_t*) d) + 1, s, size); | |||
| 461 | ||||
| 462 | return 0; | |||
| 463 | } | |||
| 464 | ||||
| 465 | int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool_Bool canonical_candidate, size_t *start) { | |||
| 466 | uint8_t *w; | |||
| 467 | int r; | |||
| 468 | ||||
| 469 | /* Append a label to a packet. Optionally, does this in DNSSEC | |||
| 470 | * canonical form, if this label is marked as a candidate for | |||
| 471 | * it, and the canonical form logic is enabled for the | |||
| 472 | * packet */ | |||
| 473 | ||||
| 474 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 474, __PRETTY_FUNCTION__); } while (0); | |||
| 475 | assert(d)do { if ((__builtin_expect(!!(!(d)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("d"), "../src/resolve/resolved-dns-packet.c" , 475, __PRETTY_FUNCTION__); } while (0); | |||
| 476 | ||||
| 477 | if (l > DNS_LABEL_MAX63) | |||
| 478 | return -E2BIG7; | |||
| 479 | ||||
| 480 | r = dns_packet_extend(p, 1 + l, (void**) &w, start); | |||
| 481 | if (r < 0) | |||
| 482 | return r; | |||
| 483 | ||||
| 484 | *(w++) = (uint8_t) l; | |||
| 485 | ||||
| 486 | if (p->canonical_form && canonical_candidate) { | |||
| 487 | size_t i; | |||
| 488 | ||||
| 489 | /* Generate in canonical form, as defined by DNSSEC | |||
| 490 | * RFC 4034, Section 6.2, i.e. all lower-case. */ | |||
| 491 | ||||
| 492 | for (i = 0; i < l; i++) | |||
| 493 | w[i] = (uint8_t) ascii_tolower(d[i]); | |||
| 494 | } else | |||
| 495 | /* Otherwise, just copy the string unaltered. This is | |||
| 496 | * essential for DNS-SD, where the casing of labels | |||
| 497 | * matters and needs to be retained. */ | |||
| 498 | memcpy(w, d, l); | |||
| 499 | ||||
| 500 | return 0; | |||
| 501 | } | |||
| 502 | ||||
| 503 | int dns_packet_append_name( | |||
| 504 | DnsPacket *p, | |||
| 505 | const char *name, | |||
| 506 | bool_Bool allow_compression, | |||
| 507 | bool_Bool canonical_candidate, | |||
| 508 | size_t *start) { | |||
| 509 | ||||
| 510 | size_t saved_size; | |||
| 511 | int r; | |||
| 512 | ||||
| 513 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 513, __PRETTY_FUNCTION__); } while (0); | |||
| 514 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/resolve/resolved-dns-packet.c" , 514, __PRETTY_FUNCTION__); } while (0); | |||
| 515 | ||||
| 516 | if (p->refuse_compression) | |||
| 517 | allow_compression = false0; | |||
| 518 | ||||
| 519 | saved_size = p->size; | |||
| 520 | ||||
| 521 | while (!dns_name_is_root(name)) { | |||
| 522 | const char *z = name; | |||
| 523 | char label[DNS_LABEL_MAX63]; | |||
| 524 | size_t n = 0; | |||
| 525 | ||||
| 526 | if (allow_compression
| |||
| 527 | n = PTR_TO_SIZE(hashmap_get(p->names, name))((size_t) ((uintptr_t) (hashmap_get(p->names, name)))); | |||
| 528 | if (n > 0) { | |||
| 529 | assert(n < p->size)do { if ((__builtin_expect(!!(!(n < p->size)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n < p->size"), "../src/resolve/resolved-dns-packet.c" , 529, __PRETTY_FUNCTION__); } while (0); | |||
| 530 | ||||
| 531 | if (n < 0x4000) { | |||
| 532 | r = dns_packet_append_uint16(p, 0xC000 | n, NULL((void*)0)); | |||
| 533 | if (r < 0) | |||
| 534 | goto fail; | |||
| 535 | ||||
| 536 | goto done; | |||
| 537 | } | |||
| 538 | } | |||
| 539 | ||||
| 540 | r = dns_label_unescape(&name, label, sizeof(label)); | |||
| 541 | if (r < 0) | |||
| 542 | goto fail; | |||
| 543 | ||||
| 544 | r = dns_packet_append_label(p, label, r, canonical_candidate, &n); | |||
| 545 | if (r < 0) | |||
| 546 | goto fail; | |||
| 547 | ||||
| 548 | if (allow_compression
| |||
| 549 | _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0); | |||
| 550 | ||||
| 551 | s = strdup(z); | |||
| 552 | if (!s) { | |||
| 553 | r = -ENOMEM12; | |||
| 554 | goto fail; | |||
| 555 | } | |||
| 556 | ||||
| 557 | r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops)internal_hashmap_ensure_allocated(&p->names, &dns_name_hash_ops ); | |||
| 558 | if (r < 0) | |||
| 559 | goto fail; | |||
| 560 | ||||
| 561 | r = hashmap_put(p->names, s, SIZE_TO_PTR(n)((void *) ((uintptr_t) (n)))); | |||
| 562 | if (r < 0) | |||
| 563 | goto fail; | |||
| 564 | ||||
| 565 | s = NULL((void*)0); | |||
| 566 | } | |||
| 567 | } | |||
| 568 | ||||
| 569 | r = dns_packet_append_uint8(p, 0, NULL((void*)0)); | |||
| 570 | if (r < 0) | |||
| 571 | return r; | |||
| 572 | ||||
| 573 | done: | |||
| 574 | if (start) | |||
| 575 | *start = saved_size; | |||
| 576 | ||||
| 577 | return 0; | |||
| 578 | ||||
| 579 | fail: | |||
| 580 | dns_packet_truncate(p, saved_size); | |||
| ||||
| 581 | return r; | |||
| 582 | } | |||
| 583 | ||||
| 584 | int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, const DnsAnswerFlags flags, size_t *start) { | |||
| 585 | size_t saved_size; | |||
| 586 | uint16_t class; | |||
| 587 | int r; | |||
| 588 | ||||
| 589 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 589, __PRETTY_FUNCTION__); } while (0); | |||
| 590 | assert(k)do { if ((__builtin_expect(!!(!(k)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("k"), "../src/resolve/resolved-dns-packet.c" , 590, __PRETTY_FUNCTION__); } while (0); | |||
| 591 | ||||
| 592 | saved_size = p->size; | |||
| 593 | ||||
| 594 | r = dns_packet_append_name(p, dns_resource_key_name(k), true1, true1, NULL((void*)0)); | |||
| 595 | if (r < 0) | |||
| 596 | goto fail; | |||
| 597 | ||||
| 598 | r = dns_packet_append_uint16(p, k->type, NULL((void*)0)); | |||
| 599 | if (r < 0) | |||
| 600 | goto fail; | |||
| 601 | ||||
| 602 | class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH(1 << 15) : k->class; | |||
| 603 | r = dns_packet_append_uint16(p, class, NULL((void*)0)); | |||
| 604 | if (r < 0) | |||
| 605 | goto fail; | |||
| 606 | ||||
| 607 | if (start) | |||
| 608 | *start = saved_size; | |||
| 609 | ||||
| 610 | return 0; | |||
| 611 | ||||
| 612 | fail: | |||
| 613 | dns_packet_truncate(p, saved_size); | |||
| 614 | return r; | |||
| 615 | } | |||
| 616 | ||||
| 617 | static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) { | |||
| 618 | size_t saved_size; | |||
| 619 | int r; | |||
| 620 | ||||
| 621 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 621, __PRETTY_FUNCTION__); } while (0); | |||
| 622 | assert(types)do { if ((__builtin_expect(!!(!(types)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("types"), "../src/resolve/resolved-dns-packet.c" , 622, __PRETTY_FUNCTION__); } while (0); | |||
| 623 | assert(length > 0)do { if ((__builtin_expect(!!(!(length > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("length > 0"), "../src/resolve/resolved-dns-packet.c" , 623, __PRETTY_FUNCTION__); } while (0); | |||
| 624 | ||||
| 625 | saved_size = p->size; | |||
| 626 | ||||
| 627 | r = dns_packet_append_uint8(p, window, NULL((void*)0)); | |||
| 628 | if (r < 0) | |||
| 629 | goto fail; | |||
| 630 | ||||
| 631 | r = dns_packet_append_uint8(p, length, NULL((void*)0)); | |||
| 632 | if (r < 0) | |||
| 633 | goto fail; | |||
| 634 | ||||
| 635 | r = dns_packet_append_blob(p, types, length, NULL((void*)0)); | |||
| 636 | if (r < 0) | |||
| 637 | goto fail; | |||
| 638 | ||||
| 639 | if (start) | |||
| 640 | *start = saved_size; | |||
| 641 | ||||
| 642 | return 0; | |||
| 643 | fail: | |||
| 644 | dns_packet_truncate(p, saved_size); | |||
| 645 | return r; | |||
| 646 | } | |||
| 647 | ||||
| 648 | static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) { | |||
| 649 | Iterator i; | |||
| 650 | uint8_t window = 0; | |||
| 651 | uint8_t entry = 0; | |||
| 652 | uint8_t bitmaps[32] = {}; | |||
| 653 | unsigned n; | |||
| 654 | size_t saved_size; | |||
| 655 | int r; | |||
| 656 | ||||
| 657 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 657, __PRETTY_FUNCTION__); } while (0); | |||
| 658 | ||||
| 659 | saved_size = p->size; | |||
| 660 | ||||
| 661 | BITMAP_FOREACH(n, types, i)for ((i).idx = 0; bitmap_iterate((types), &(i), (unsigned *)&(n)); ) { | |||
| 662 | assert(n <= 0xffff)do { if ((__builtin_expect(!!(!(n <= 0xffff)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n <= 0xffff"), "../src/resolve/resolved-dns-packet.c" , 662, __PRETTY_FUNCTION__); } while (0); | |||
| 663 | ||||
| 664 | if ((n >> 8) != window && bitmaps[entry / 8] != 0) { | |||
| 665 | r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL((void*)0)); | |||
| 666 | if (r < 0) | |||
| 667 | goto fail; | |||
| 668 | ||||
| 669 | zero(bitmaps)(({ size_t _l_ = (sizeof(bitmaps)); void *_x_ = (&(bitmaps )); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); })); | |||
| 670 | } | |||
| 671 | ||||
| 672 | window = n >> 8; | |||
| 673 | entry = n & 255; | |||
| 674 | ||||
| 675 | bitmaps[entry / 8] |= 1 << (7 - (entry % 8)); | |||
| 676 | } | |||
| 677 | ||||
| 678 | if (bitmaps[entry / 8] != 0) { | |||
| 679 | r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL((void*)0)); | |||
| 680 | if (r < 0) | |||
| 681 | goto fail; | |||
| 682 | } | |||
| 683 | ||||
| 684 | if (start) | |||
| 685 | *start = saved_size; | |||
| 686 | ||||
| 687 | return 0; | |||
| 688 | fail: | |||
| 689 | dns_packet_truncate(p, saved_size); | |||
| 690 | return r; | |||
| 691 | } | |||
| 692 | ||||
| 693 | /* Append the OPT pseudo-RR described in RFC6891 */ | |||
| 694 | int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool_Bool edns0_do, int rcode, size_t *start) { | |||
| 695 | size_t saved_size; | |||
| 696 | int r; | |||
| 697 | ||||
| 698 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 698, __PRETTY_FUNCTION__); } while (0); | |||
| 699 | /* we must never advertise supported packet size smaller than the legacy max */ | |||
| 700 | assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX)do { if ((__builtin_expect(!!(!(max_udp_size >= 512u)),0)) ) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX" ), "../src/resolve/resolved-dns-packet.c", 700, __PRETTY_FUNCTION__ ); } while (0); | |||
| 701 | assert(rcode >= 0)do { if ((__builtin_expect(!!(!(rcode >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rcode >= 0"), "../src/resolve/resolved-dns-packet.c" , 701, __PRETTY_FUNCTION__); } while (0); | |||
| 702 | assert(rcode <= _DNS_RCODE_MAX)do { if ((__builtin_expect(!!(!(rcode <= _DNS_RCODE_MAX)), 0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("rcode <= _DNS_RCODE_MAX" ), "../src/resolve/resolved-dns-packet.c", 702, __PRETTY_FUNCTION__ ); } while (0); | |||
| 703 | ||||
| 704 | if (p->opt_start != (size_t) -1) | |||
| 705 | return -EBUSY16; | |||
| 706 | ||||
| 707 | assert(p->opt_size == (size_t) -1)do { if ((__builtin_expect(!!(!(p->opt_size == (size_t) -1 )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("p->opt_size == (size_t) -1" ), "../src/resolve/resolved-dns-packet.c", 707, __PRETTY_FUNCTION__ ); } while (0); | |||
| 708 | ||||
| 709 | saved_size = p->size; | |||
| 710 | ||||
| 711 | /* empty name */ | |||
| 712 | r = dns_packet_append_uint8(p, 0, NULL((void*)0)); | |||
| 713 | if (r < 0) | |||
| 714 | return r; | |||
| 715 | ||||
| 716 | /* type */ | |||
| 717 | r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL((void*)0)); | |||
| 718 | if (r < 0) | |||
| 719 | goto fail; | |||
| 720 | ||||
| 721 | /* class: maximum udp packet that can be received */ | |||
| 722 | r = dns_packet_append_uint16(p, max_udp_size, NULL((void*)0)); | |||
| 723 | if (r < 0) | |||
| 724 | goto fail; | |||
| 725 | ||||
| 726 | /* extended RCODE and VERSION */ | |||
| 727 | r = dns_packet_append_uint16(p, ((uint16_t) rcode & 0x0FF0) << 4, NULL((void*)0)); | |||
| 728 | if (r < 0) | |||
| 729 | goto fail; | |||
| 730 | ||||
| 731 | /* flags: DNSSEC OK (DO), see RFC3225 */ | |||
| 732 | r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO(1<<15) : 0, NULL((void*)0)); | |||
| 733 | if (r < 0) | |||
| 734 | goto fail; | |||
| 735 | ||||
| 736 | /* RDLENGTH */ | |||
| 737 | if (edns0_do && !DNS_PACKET_QR(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 15) & 1)) { | |||
| 738 | /* If DO is on and this is not a reply, also append RFC6975 Algorithm data */ | |||
| 739 | ||||
| 740 | static const uint8_t rfc6975[] = { | |||
| 741 | ||||
| 742 | 0, 5, /* OPTION_CODE: DAU */ | |||
| 743 | #if HAVE_GCRYPT1 && GCRYPT_VERSION_NUMBER0x010903 >= 0x010600 | |||
| 744 | 0, 7, /* LIST_LENGTH */ | |||
| 745 | #else | |||
| 746 | 0, 6, /* LIST_LENGTH */ | |||
| 747 | #endif | |||
| 748 | DNSSEC_ALGORITHM_RSASHA1, | |||
| 749 | DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1, | |||
| 750 | DNSSEC_ALGORITHM_RSASHA256, | |||
| 751 | DNSSEC_ALGORITHM_RSASHA512, | |||
| 752 | DNSSEC_ALGORITHM_ECDSAP256SHA256, | |||
| 753 | DNSSEC_ALGORITHM_ECDSAP384SHA384, | |||
| 754 | #if HAVE_GCRYPT1 && GCRYPT_VERSION_NUMBER0x010903 >= 0x010600 | |||
| 755 | DNSSEC_ALGORITHM_ED25519, | |||
| 756 | #endif | |||
| 757 | ||||
| 758 | 0, 6, /* OPTION_CODE: DHU */ | |||
| 759 | 0, 3, /* LIST_LENGTH */ | |||
| 760 | DNSSEC_DIGEST_SHA1, | |||
| 761 | DNSSEC_DIGEST_SHA256, | |||
| 762 | DNSSEC_DIGEST_SHA384, | |||
| 763 | ||||
| 764 | 0, 7, /* OPTION_CODE: N3U */ | |||
| 765 | 0, 1, /* LIST_LENGTH */ | |||
| 766 | NSEC3_ALGORITHM_SHA1, | |||
| 767 | }; | |||
| 768 | ||||
| 769 | r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL((void*)0)); | |||
| 770 | if (r < 0) | |||
| 771 | goto fail; | |||
| 772 | ||||
| 773 | r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL((void*)0)); | |||
| 774 | } else | |||
| 775 | r = dns_packet_append_uint16(p, 0, NULL((void*)0)); | |||
| 776 | if (r < 0) | |||
| 777 | goto fail; | |||
| 778 | ||||
| 779 | DNS_PACKET_HEADER(p)((DnsPacketHeader*) DNS_PACKET_DATA(p))->arcount = htobe16(DNS_PACKET_ARCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->arcount) + 1); | |||
| 780 | ||||
| 781 | p->opt_start = saved_size; | |||
| 782 | p->opt_size = p->size - saved_size; | |||
| 783 | ||||
| 784 | if (start) | |||
| 785 | *start = saved_size; | |||
| 786 | ||||
| 787 | return 0; | |||
| 788 | ||||
| 789 | fail: | |||
| 790 | dns_packet_truncate(p, saved_size); | |||
| 791 | return r; | |||
| 792 | } | |||
| 793 | ||||
| 794 | int dns_packet_truncate_opt(DnsPacket *p) { | |||
| 795 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 795, __PRETTY_FUNCTION__); } while (0); | |||
| 796 | ||||
| 797 | if (p->opt_start == (size_t) -1) { | |||
| 798 | assert(p->opt_size == (size_t) -1)do { if ((__builtin_expect(!!(!(p->opt_size == (size_t) -1 )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("p->opt_size == (size_t) -1" ), "../src/resolve/resolved-dns-packet.c", 798, __PRETTY_FUNCTION__ ); } while (0); | |||
| 799 | return 0; | |||
| 800 | } | |||
| 801 | ||||
| 802 | assert(p->opt_size != (size_t) -1)do { if ((__builtin_expect(!!(!(p->opt_size != (size_t) -1 )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("p->opt_size != (size_t) -1" ), "../src/resolve/resolved-dns-packet.c", 802, __PRETTY_FUNCTION__ ); } while (0); | |||
| 803 | assert(DNS_PACKET_ARCOUNT(p) > 0)do { if ((__builtin_expect(!!(!(be16toh(((DnsPacketHeader*) DNS_PACKET_DATA (p))->arcount) > 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("DNS_PACKET_ARCOUNT(p) > 0"), "../src/resolve/resolved-dns-packet.c" , 803, __PRETTY_FUNCTION__); } while (0); | |||
| 804 | ||||
| 805 | if (p->opt_start + p->opt_size != p->size) | |||
| 806 | return -EBUSY16; | |||
| 807 | ||||
| 808 | dns_packet_truncate(p, p->opt_start); | |||
| 809 | DNS_PACKET_HEADER(p)((DnsPacketHeader*) DNS_PACKET_DATA(p))->arcount = htobe16(DNS_PACKET_ARCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->arcount) - 1); | |||
| 810 | p->opt_start = p->opt_size = (size_t) -1; | |||
| 811 | ||||
| 812 | return 1; | |||
| 813 | } | |||
| 814 | ||||
| 815 | int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start) { | |||
| 816 | ||||
| 817 | size_t saved_size, rdlength_offset, end, rdlength, rds; | |||
| 818 | uint32_t ttl; | |||
| 819 | int r; | |||
| 820 | ||||
| 821 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 821, __PRETTY_FUNCTION__); } while (0); | |||
| 822 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-packet.c" , 822, __PRETTY_FUNCTION__); } while (0); | |||
| 823 | ||||
| 824 | saved_size = p->size; | |||
| 825 | ||||
| 826 | r = dns_packet_append_key(p, rr->key, flags, NULL((void*)0)); | |||
| 827 | if (r < 0) | |||
| 828 | goto fail; | |||
| 829 | ||||
| 830 | ttl = flags & DNS_ANSWER_GOODBYE ? 0 : rr->ttl; | |||
| 831 | r = dns_packet_append_uint32(p, ttl, NULL((void*)0)); | |||
| 832 | if (r < 0) | |||
| 833 | goto fail; | |||
| 834 | ||||
| 835 | /* Initially we write 0 here */ | |||
| 836 | r = dns_packet_append_uint16(p, 0, &rdlength_offset); | |||
| 837 | if (r < 0) | |||
| 838 | goto fail; | |||
| 839 | ||||
| 840 | rds = p->size - saved_size; | |||
| 841 | ||||
| 842 | switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { | |||
| 843 | ||||
| 844 | case DNS_TYPE_SRV: | |||
| 845 | r = dns_packet_append_uint16(p, rr->srv.priority, NULL((void*)0)); | |||
| 846 | if (r < 0) | |||
| 847 | goto fail; | |||
| 848 | ||||
| 849 | r = dns_packet_append_uint16(p, rr->srv.weight, NULL((void*)0)); | |||
| 850 | if (r < 0) | |||
| 851 | goto fail; | |||
| 852 | ||||
| 853 | r = dns_packet_append_uint16(p, rr->srv.port, NULL((void*)0)); | |||
| 854 | if (r < 0) | |||
| 855 | goto fail; | |||
| 856 | ||||
| 857 | r = dns_packet_append_name(p, rr->srv.name, true1, false0, NULL((void*)0)); | |||
| 858 | break; | |||
| 859 | ||||
| 860 | case DNS_TYPE_PTR: | |||
| 861 | case DNS_TYPE_NS: | |||
| 862 | case DNS_TYPE_CNAME: | |||
| 863 | case DNS_TYPE_DNAME: | |||
| 864 | r = dns_packet_append_name(p, rr->ptr.name, true1, false0, NULL((void*)0)); | |||
| 865 | break; | |||
| 866 | ||||
| 867 | case DNS_TYPE_HINFO: | |||
| 868 | r = dns_packet_append_string(p, rr->hinfo.cpu, NULL((void*)0)); | |||
| 869 | if (r < 0) | |||
| 870 | goto fail; | |||
| 871 | ||||
| 872 | r = dns_packet_append_string(p, rr->hinfo.os, NULL((void*)0)); | |||
| 873 | break; | |||
| 874 | ||||
| 875 | case DNS_TYPE_SPF: /* exactly the same as TXT */ | |||
| 876 | case DNS_TYPE_TXT: | |||
| 877 | ||||
| 878 | if (!rr->txt.items) { | |||
| 879 | /* RFC 6763, section 6.1 suggests to generate | |||
| 880 | * single empty string for an empty array. */ | |||
| 881 | ||||
| 882 | r = dns_packet_append_raw_string(p, NULL((void*)0), 0, NULL((void*)0)); | |||
| 883 | if (r < 0) | |||
| 884 | goto fail; | |||
| 885 | } else { | |||
| 886 | DnsTxtItem *i; | |||
| 887 | ||||
| 888 | LIST_FOREACH(items, i, rr->txt.items)for ((i) = (rr->txt.items); (i); (i) = (i)->items_next) { | |||
| 889 | r = dns_packet_append_raw_string(p, i->data, i->length, NULL((void*)0)); | |||
| 890 | if (r < 0) | |||
| 891 | goto fail; | |||
| 892 | } | |||
| 893 | } | |||
| 894 | ||||
| 895 | r = 0; | |||
| 896 | break; | |||
| 897 | ||||
| 898 | case DNS_TYPE_A: | |||
| 899 | r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL((void*)0)); | |||
| 900 | break; | |||
| 901 | ||||
| 902 | case DNS_TYPE_AAAA: | |||
| 903 | r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL((void*)0)); | |||
| 904 | break; | |||
| 905 | ||||
| 906 | case DNS_TYPE_SOA: | |||
| 907 | r = dns_packet_append_name(p, rr->soa.mname, true1, false0, NULL((void*)0)); | |||
| 908 | if (r < 0) | |||
| 909 | goto fail; | |||
| 910 | ||||
| 911 | r = dns_packet_append_name(p, rr->soa.rname, true1, false0, NULL((void*)0)); | |||
| 912 | if (r < 0) | |||
| 913 | goto fail; | |||
| 914 | ||||
| 915 | r = dns_packet_append_uint32(p, rr->soa.serial, NULL((void*)0)); | |||
| 916 | if (r < 0) | |||
| 917 | goto fail; | |||
| 918 | ||||
| 919 | r = dns_packet_append_uint32(p, rr->soa.refresh, NULL((void*)0)); | |||
| 920 | if (r < 0) | |||
| 921 | goto fail; | |||
| 922 | ||||
| 923 | r = dns_packet_append_uint32(p, rr->soa.retry, NULL((void*)0)); | |||
| 924 | if (r < 0) | |||
| 925 | goto fail; | |||
| 926 | ||||
| 927 | r = dns_packet_append_uint32(p, rr->soa.expire, NULL((void*)0)); | |||
| 928 | if (r < 0) | |||
| 929 | goto fail; | |||
| 930 | ||||
| 931 | r = dns_packet_append_uint32(p, rr->soa.minimum, NULL((void*)0)); | |||
| 932 | break; | |||
| 933 | ||||
| 934 | case DNS_TYPE_MX: | |||
| 935 | r = dns_packet_append_uint16(p, rr->mx.priority, NULL((void*)0)); | |||
| 936 | if (r < 0) | |||
| 937 | goto fail; | |||
| 938 | ||||
| 939 | r = dns_packet_append_name(p, rr->mx.exchange, true1, false0, NULL((void*)0)); | |||
| 940 | break; | |||
| 941 | ||||
| 942 | case DNS_TYPE_LOC: | |||
| 943 | r = dns_packet_append_uint8(p, rr->loc.version, NULL((void*)0)); | |||
| 944 | if (r < 0) | |||
| 945 | goto fail; | |||
| 946 | ||||
| 947 | r = dns_packet_append_uint8(p, rr->loc.size, NULL((void*)0)); | |||
| 948 | if (r < 0) | |||
| 949 | goto fail; | |||
| 950 | ||||
| 951 | r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL((void*)0)); | |||
| 952 | if (r < 0) | |||
| 953 | goto fail; | |||
| 954 | ||||
| 955 | r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL((void*)0)); | |||
| 956 | if (r < 0) | |||
| 957 | goto fail; | |||
| 958 | ||||
| 959 | r = dns_packet_append_uint32(p, rr->loc.latitude, NULL((void*)0)); | |||
| 960 | if (r < 0) | |||
| 961 | goto fail; | |||
| 962 | ||||
| 963 | r = dns_packet_append_uint32(p, rr->loc.longitude, NULL((void*)0)); | |||
| 964 | if (r < 0) | |||
| 965 | goto fail; | |||
| 966 | ||||
| 967 | r = dns_packet_append_uint32(p, rr->loc.altitude, NULL((void*)0)); | |||
| 968 | break; | |||
| 969 | ||||
| 970 | case DNS_TYPE_DS: | |||
| 971 | r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL((void*)0)); | |||
| 972 | if (r < 0) | |||
| 973 | goto fail; | |||
| 974 | ||||
| 975 | r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL((void*)0)); | |||
| 976 | if (r < 0) | |||
| 977 | goto fail; | |||
| 978 | ||||
| 979 | r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL((void*)0)); | |||
| 980 | if (r < 0) | |||
| 981 | goto fail; | |||
| 982 | ||||
| 983 | r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL((void*)0)); | |||
| 984 | break; | |||
| 985 | ||||
| 986 | case DNS_TYPE_SSHFP: | |||
| 987 | r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL((void*)0)); | |||
| 988 | if (r < 0) | |||
| 989 | goto fail; | |||
| 990 | ||||
| 991 | r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL((void*)0)); | |||
| 992 | if (r < 0) | |||
| 993 | goto fail; | |||
| 994 | ||||
| 995 | r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL((void*)0)); | |||
| 996 | break; | |||
| 997 | ||||
| 998 | case DNS_TYPE_DNSKEY: | |||
| 999 | r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL((void*)0)); | |||
| 1000 | if (r < 0) | |||
| 1001 | goto fail; | |||
| 1002 | ||||
| 1003 | r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL((void*)0)); | |||
| 1004 | if (r < 0) | |||
| 1005 | goto fail; | |||
| 1006 | ||||
| 1007 | r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL((void*)0)); | |||
| 1008 | if (r < 0) | |||
| 1009 | goto fail; | |||
| 1010 | ||||
| 1011 | r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL((void*)0)); | |||
| 1012 | break; | |||
| 1013 | ||||
| 1014 | case DNS_TYPE_RRSIG: | |||
| 1015 | r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL((void*)0)); | |||
| 1016 | if (r < 0) | |||
| 1017 | goto fail; | |||
| 1018 | ||||
| 1019 | r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL((void*)0)); | |||
| 1020 | if (r < 0) | |||
| 1021 | goto fail; | |||
| 1022 | ||||
| 1023 | r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL((void*)0)); | |||
| 1024 | if (r < 0) | |||
| 1025 | goto fail; | |||
| 1026 | ||||
| 1027 | r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL((void*)0)); | |||
| 1028 | if (r < 0) | |||
| 1029 | goto fail; | |||
| 1030 | ||||
| 1031 | r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL((void*)0)); | |||
| 1032 | if (r < 0) | |||
| 1033 | goto fail; | |||
| 1034 | ||||
| 1035 | r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL((void*)0)); | |||
| 1036 | if (r < 0) | |||
| 1037 | goto fail; | |||
| 1038 | ||||
| 1039 | r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL((void*)0)); | |||
| 1040 | if (r < 0) | |||
| 1041 | goto fail; | |||
| 1042 | ||||
| 1043 | r = dns_packet_append_name(p, rr->rrsig.signer, false0, true1, NULL((void*)0)); | |||
| 1044 | if (r < 0) | |||
| 1045 | goto fail; | |||
| 1046 | ||||
| 1047 | r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL((void*)0)); | |||
| 1048 | break; | |||
| 1049 | ||||
| 1050 | case DNS_TYPE_NSEC: | |||
| 1051 | r = dns_packet_append_name(p, rr->nsec.next_domain_name, false0, false0, NULL((void*)0)); | |||
| 1052 | if (r < 0) | |||
| 1053 | goto fail; | |||
| 1054 | ||||
| 1055 | r = dns_packet_append_types(p, rr->nsec.types, NULL((void*)0)); | |||
| 1056 | if (r < 0) | |||
| 1057 | goto fail; | |||
| 1058 | ||||
| 1059 | break; | |||
| 1060 | ||||
| 1061 | case DNS_TYPE_NSEC3: | |||
| 1062 | r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL((void*)0)); | |||
| 1063 | if (r < 0) | |||
| 1064 | goto fail; | |||
| 1065 | ||||
| 1066 | r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL((void*)0)); | |||
| 1067 | if (r < 0) | |||
| 1068 | goto fail; | |||
| 1069 | ||||
| 1070 | r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL((void*)0)); | |||
| 1071 | if (r < 0) | |||
| 1072 | goto fail; | |||
| 1073 | ||||
| 1074 | r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL((void*)0)); | |||
| 1075 | if (r < 0) | |||
| 1076 | goto fail; | |||
| 1077 | ||||
| 1078 | r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL((void*)0)); | |||
| 1079 | if (r < 0) | |||
| 1080 | goto fail; | |||
| 1081 | ||||
| 1082 | r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL((void*)0)); | |||
| 1083 | if (r < 0) | |||
| 1084 | goto fail; | |||
| 1085 | ||||
| 1086 | r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL((void*)0)); | |||
| 1087 | if (r < 0) | |||
| 1088 | goto fail; | |||
| 1089 | ||||
| 1090 | r = dns_packet_append_types(p, rr->nsec3.types, NULL((void*)0)); | |||
| 1091 | if (r < 0) | |||
| 1092 | goto fail; | |||
| 1093 | ||||
| 1094 | break; | |||
| 1095 | ||||
| 1096 | case DNS_TYPE_TLSA: | |||
| 1097 | r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL((void*)0)); | |||
| 1098 | if (r < 0) | |||
| 1099 | goto fail; | |||
| 1100 | ||||
| 1101 | r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL((void*)0)); | |||
| 1102 | if (r < 0) | |||
| 1103 | goto fail; | |||
| 1104 | ||||
| 1105 | r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL((void*)0)); | |||
| 1106 | if (r < 0) | |||
| 1107 | goto fail; | |||
| 1108 | ||||
| 1109 | r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL((void*)0)); | |||
| 1110 | break; | |||
| 1111 | ||||
| 1112 | case DNS_TYPE_CAA: | |||
| 1113 | r = dns_packet_append_uint8(p, rr->caa.flags, NULL((void*)0)); | |||
| 1114 | if (r < 0) | |||
| 1115 | goto fail; | |||
| 1116 | ||||
| 1117 | r = dns_packet_append_string(p, rr->caa.tag, NULL((void*)0)); | |||
| 1118 | if (r < 0) | |||
| 1119 | goto fail; | |||
| 1120 | ||||
| 1121 | r = dns_packet_append_blob(p, rr->caa.value, rr->caa.value_size, NULL((void*)0)); | |||
| 1122 | break; | |||
| 1123 | ||||
| 1124 | case DNS_TYPE_OPT: | |||
| 1125 | case DNS_TYPE_OPENPGPKEY: | |||
| 1126 | case _DNS_TYPE_INVALID: /* unparseable */ | |||
| 1127 | default: | |||
| 1128 | ||||
| 1129 | r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL((void*)0)); | |||
| 1130 | break; | |||
| 1131 | } | |||
| 1132 | if (r < 0) | |||
| 1133 | goto fail; | |||
| 1134 | ||||
| 1135 | /* Let's calculate the actual data size and update the field */ | |||
| 1136 | rdlength = p->size - rdlength_offset - sizeof(uint16_t); | |||
| 1137 | if (rdlength > 0xFFFF) { | |||
| 1138 | r = -ENOSPC28; | |||
| 1139 | goto fail; | |||
| 1140 | } | |||
| 1141 | ||||
| 1142 | end = p->size; | |||
| 1143 | p->size = rdlength_offset; | |||
| 1144 | r = dns_packet_append_uint16(p, rdlength, NULL((void*)0)); | |||
| 1145 | if (r < 0) | |||
| 1146 | goto fail; | |||
| 1147 | p->size = end; | |||
| 1148 | ||||
| 1149 | if (start) | |||
| 1150 | *start = saved_size; | |||
| 1151 | ||||
| 1152 | if (rdata_start) | |||
| 1153 | *rdata_start = rds; | |||
| 1154 | ||||
| 1155 | return 0; | |||
| 1156 | ||||
| 1157 | fail: | |||
| 1158 | dns_packet_truncate(p, saved_size); | |||
| 1159 | return r; | |||
| 1160 | } | |||
| 1161 | ||||
| 1162 | int dns_packet_append_question(DnsPacket *p, DnsQuestion *q) { | |||
| 1163 | DnsResourceKey *key; | |||
| 1164 | int r; | |||
| 1165 | ||||
| 1166 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1166, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 1167 | ||||
| 1168 | DNS_QUESTION_FOREACH(key, q)for (size_t __unique_prefix_i17 = ({ (key) = ((q) && ( q)->n_keys > 0) ? (q)->keys[0] : ((void*)0); 0; }); ( q) && (__unique_prefix_i17 < (q)->n_keys); __unique_prefix_i17 ++, (key) = (__unique_prefix_i17 < (q)->n_keys ? (q)-> keys[__unique_prefix_i17] : ((void*)0))) { | |||
| 1169 | r = dns_packet_append_key(p, key, 0, NULL((void*)0)); | |||
| 1170 | if (r < 0) | |||
| 1171 | return r; | |||
| 1172 | } | |||
| 1173 | ||||
| 1174 | return 0; | |||
| 1175 | } | |||
| 1176 | ||||
| 1177 | int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a) { | |||
| 1178 | DnsResourceRecord *rr; | |||
| 1179 | DnsAnswerFlags flags; | |||
| 1180 | int r; | |||
| 1181 | ||||
| 1182 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1182, __PRETTY_FUNCTION__); } while (0); | |||
| 1183 | ||||
| 1184 | DNS_ANSWER_FOREACH_FLAGS(rr, flags, a)for (size_t __unique_prefix_i18 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i18 < (a )->n_rrs); __unique_prefix_i18++, (rr) = ((__unique_prefix_i18 < (a)->n_rrs) ? (a)->items[__unique_prefix_i18].rr : ((void*)0)), (flags) = ((__unique_prefix_i18 < (a)->n_rrs ) ? (a)->items[__unique_prefix_i18].flags : 0)) { | |||
| 1185 | r = dns_packet_append_rr(p, rr, flags, NULL((void*)0), NULL((void*)0)); | |||
| 1186 | if (r < 0) | |||
| 1187 | return r; | |||
| 1188 | } | |||
| 1189 | ||||
| 1190 | return 0; | |||
| 1191 | } | |||
| 1192 | ||||
| 1193 | int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) { | |||
| 1194 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1194, __PRETTY_FUNCTION__); } while (0); | |||
| 1195 | ||||
| 1196 | if (p->rindex + sz > p->size) | |||
| 1197 | return -EMSGSIZE90; | |||
| 1198 | ||||
| 1199 | if (ret) | |||
| 1200 | *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex; | |||
| 1201 | ||||
| 1202 | if (start) | |||
| 1203 | *start = p->rindex; | |||
| 1204 | ||||
| 1205 | p->rindex += sz; | |||
| 1206 | return 0; | |||
| 1207 | } | |||
| 1208 | ||||
| 1209 | void dns_packet_rewind(DnsPacket *p, size_t idx) { | |||
| 1210 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1210, __PRETTY_FUNCTION__); } while (0); | |||
| 1211 | assert(idx <= p->size)do { if ((__builtin_expect(!!(!(idx <= p->size)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("idx <= p->size"), "../src/resolve/resolved-dns-packet.c" , 1211, __PRETTY_FUNCTION__); } while (0); | |||
| 1212 | assert(idx >= DNS_PACKET_HEADER_SIZE)do { if ((__builtin_expect(!!(!(idx >= sizeof(DnsPacketHeader ))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("idx >= DNS_PACKET_HEADER_SIZE" ), "../src/resolve/resolved-dns-packet.c", 1212, __PRETTY_FUNCTION__ ); } while (0); | |||
| 1213 | ||||
| 1214 | p->rindex = idx; | |||
| 1215 | } | |||
| 1216 | ||||
| 1217 | int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) { | |||
| 1218 | const void *q; | |||
| 1219 | int r; | |||
| 1220 | ||||
| 1221 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1221, __PRETTY_FUNCTION__); } while (0); | |||
| 1222 | assert(d)do { if ((__builtin_expect(!!(!(d)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("d"), "../src/resolve/resolved-dns-packet.c" , 1222, __PRETTY_FUNCTION__); } while (0); | |||
| 1223 | ||||
| 1224 | r = dns_packet_read(p, sz, &q, start); | |||
| 1225 | if (r < 0) | |||
| 1226 | return r; | |||
| 1227 | ||||
| 1228 | memcpy(d, q, sz); | |||
| 1229 | return 0; | |||
| 1230 | } | |||
| 1231 | ||||
| 1232 | static int dns_packet_read_memdup( | |||
| 1233 | DnsPacket *p, size_t size, | |||
| 1234 | void **ret, size_t *ret_size, | |||
| 1235 | size_t *ret_start) { | |||
| 1236 | ||||
| 1237 | const void *src; | |||
| 1238 | size_t start; | |||
| 1239 | int r; | |||
| 1240 | ||||
| 1241 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1241, __PRETTY_FUNCTION__); } while (0); | |||
| 1242 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-packet.c" , 1242, __PRETTY_FUNCTION__); } while (0); | |||
| 1243 | ||||
| 1244 | r = dns_packet_read(p, size, &src, &start); | |||
| 1245 | if (r < 0) | |||
| 1246 | return r; | |||
| 1247 | ||||
| 1248 | if (size <= 0) | |||
| 1249 | *ret = NULL((void*)0); | |||
| 1250 | else { | |||
| 1251 | void *copy; | |||
| 1252 | ||||
| 1253 | copy = memdup(src, size); | |||
| 1254 | if (!copy) | |||
| 1255 | return -ENOMEM12; | |||
| 1256 | ||||
| 1257 | *ret = copy; | |||
| 1258 | } | |||
| 1259 | ||||
| 1260 | if (ret_size) | |||
| 1261 | *ret_size = size; | |||
| 1262 | if (ret_start) | |||
| 1263 | *ret_start = start; | |||
| 1264 | ||||
| 1265 | return 0; | |||
| 1266 | } | |||
| 1267 | ||||
| 1268 | int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) { | |||
| 1269 | const void *d; | |||
| 1270 | int r; | |||
| 1271 | ||||
| 1272 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1272, __PRETTY_FUNCTION__); } while (0); | |||
| 1273 | ||||
| 1274 | r = dns_packet_read(p, sizeof(uint8_t), &d, start); | |||
| 1275 | if (r < 0) | |||
| 1276 | return r; | |||
| 1277 | ||||
| 1278 | *ret = ((uint8_t*) d)[0]; | |||
| 1279 | return 0; | |||
| 1280 | } | |||
| 1281 | ||||
| 1282 | int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) { | |||
| 1283 | const void *d; | |||
| 1284 | int r; | |||
| 1285 | ||||
| 1286 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1286, __PRETTY_FUNCTION__); } while (0); | |||
| 1287 | ||||
| 1288 | r = dns_packet_read(p, sizeof(uint16_t), &d, start); | |||
| 1289 | if (r < 0) | |||
| 1290 | return r; | |||
| 1291 | ||||
| 1292 | *ret = unaligned_read_be16(d); | |||
| 1293 | ||||
| 1294 | return 0; | |||
| 1295 | } | |||
| 1296 | ||||
| 1297 | int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) { | |||
| 1298 | const void *d; | |||
| 1299 | int r; | |||
| 1300 | ||||
| 1301 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1301, __PRETTY_FUNCTION__); } while (0); | |||
| 1302 | ||||
| 1303 | r = dns_packet_read(p, sizeof(uint32_t), &d, start); | |||
| 1304 | if (r < 0) | |||
| 1305 | return r; | |||
| 1306 | ||||
| 1307 | *ret = unaligned_read_be32(d); | |||
| 1308 | ||||
| 1309 | return 0; | |||
| 1310 | } | |||
| 1311 | ||||
| 1312 | int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) { | |||
| 1313 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder; | |||
| 1314 | const void *d; | |||
| 1315 | char *t; | |||
| 1316 | uint8_t c; | |||
| 1317 | int r; | |||
| 1318 | ||||
| 1319 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1319, __PRETTY_FUNCTION__); } while (0); | |||
| 1320 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 1321 | ||||
| 1322 | r = dns_packet_read_uint8(p, &c, NULL((void*)0)); | |||
| 1323 | if (r < 0) | |||
| 1324 | return r; | |||
| 1325 | ||||
| 1326 | r = dns_packet_read(p, c, &d, NULL((void*)0)); | |||
| 1327 | if (r < 0) | |||
| 1328 | return r; | |||
| 1329 | ||||
| 1330 | if (memchr(d, 0, c)) | |||
| 1331 | return -EBADMSG74; | |||
| 1332 | ||||
| 1333 | t = strndup(d, c); | |||
| 1334 | if (!t) | |||
| 1335 | return -ENOMEM12; | |||
| 1336 | ||||
| 1337 | if (!utf8_is_valid(t)) { | |||
| 1338 | free(t); | |||
| 1339 | return -EBADMSG74; | |||
| 1340 | } | |||
| 1341 | ||||
| 1342 | *ret = t; | |||
| 1343 | ||||
| 1344 | if (start) | |||
| 1345 | *start = rewinder.saved_rindex; | |||
| 1346 | CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0); | |||
| 1347 | ||||
| 1348 | return 0; | |||
| 1349 | } | |||
| 1350 | ||||
| 1351 | int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) { | |||
| 1352 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder; | |||
| 1353 | uint8_t c; | |||
| 1354 | int r; | |||
| 1355 | ||||
| 1356 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1356, __PRETTY_FUNCTION__); } while (0); | |||
| 1357 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 1358 | ||||
| 1359 | r = dns_packet_read_uint8(p, &c, NULL((void*)0)); | |||
| 1360 | if (r < 0) | |||
| 1361 | return r; | |||
| 1362 | ||||
| 1363 | r = dns_packet_read(p, c, ret, NULL((void*)0)); | |||
| 1364 | if (r < 0) | |||
| 1365 | return r; | |||
| 1366 | ||||
| 1367 | if (size) | |||
| 1368 | *size = c; | |||
| 1369 | if (start) | |||
| 1370 | *start = rewinder.saved_rindex; | |||
| 1371 | CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0); | |||
| 1372 | ||||
| 1373 | return 0; | |||
| 1374 | } | |||
| 1375 | ||||
| 1376 | int dns_packet_read_name( | |||
| 1377 | DnsPacket *p, | |||
| 1378 | char **_ret, | |||
| 1379 | bool_Bool allow_compression, | |||
| 1380 | size_t *start) { | |||
| 1381 | ||||
| 1382 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder; | |||
| 1383 | size_t after_rindex = 0, jump_barrier; | |||
| 1384 | _cleanup_free___attribute__((cleanup(freep))) char *ret = NULL((void*)0); | |||
| 1385 | size_t n = 0, allocated = 0; | |||
| 1386 | bool_Bool first = true1; | |||
| 1387 | int r; | |||
| 1388 | ||||
| 1389 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1389, __PRETTY_FUNCTION__); } while (0); | |||
| 1390 | assert(_ret)do { if ((__builtin_expect(!!(!(_ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_ret"), "../src/resolve/resolved-dns-packet.c" , 1390, __PRETTY_FUNCTION__); } while (0); | |||
| 1391 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 1392 | jump_barrier = p->rindex; | |||
| 1393 | ||||
| 1394 | if (p->refuse_compression) | |||
| 1395 | allow_compression = false0; | |||
| 1396 | ||||
| 1397 | for (;;) { | |||
| 1398 | uint8_t c, d; | |||
| 1399 | ||||
| 1400 | r = dns_packet_read_uint8(p, &c, NULL((void*)0)); | |||
| 1401 | if (r < 0) | |||
| 1402 | return r; | |||
| 1403 | ||||
| 1404 | if (c == 0) | |||
| 1405 | /* End of name */ | |||
| 1406 | break; | |||
| 1407 | else if (c <= 63) { | |||
| 1408 | const char *label; | |||
| 1409 | ||||
| 1410 | /* Literal label */ | |||
| 1411 | r = dns_packet_read(p, c, (const void**) &label, NULL((void*)0)); | |||
| 1412 | if (r < 0) | |||
| 1413 | return r; | |||
| 1414 | ||||
| 1415 | if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)greedy_realloc((void**) &(ret), &(allocated), (n + !first + (63*4+1)), sizeof((ret)[0]))) | |||
| 1416 | return -ENOMEM12; | |||
| 1417 | ||||
| 1418 | if (first) | |||
| 1419 | first = false0; | |||
| 1420 | else | |||
| 1421 | ret[n++] = '.'; | |||
| 1422 | ||||
| 1423 | r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX(63*4+1)); | |||
| 1424 | if (r < 0) | |||
| 1425 | return r; | |||
| 1426 | ||||
| 1427 | n += r; | |||
| 1428 | continue; | |||
| 1429 | } else if (allow_compression && (c & 0xc0) == 0xc0) { | |||
| 1430 | uint16_t ptr; | |||
| 1431 | ||||
| 1432 | /* Pointer */ | |||
| 1433 | r = dns_packet_read_uint8(p, &d, NULL((void*)0)); | |||
| 1434 | if (r < 0) | |||
| 1435 | return r; | |||
| 1436 | ||||
| 1437 | ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d; | |||
| 1438 | if (ptr < DNS_PACKET_HEADER_SIZEsizeof(DnsPacketHeader) || ptr >= jump_barrier) | |||
| 1439 | return -EBADMSG74; | |||
| 1440 | ||||
| 1441 | if (after_rindex == 0) | |||
| 1442 | after_rindex = p->rindex; | |||
| 1443 | ||||
| 1444 | /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */ | |||
| 1445 | jump_barrier = ptr; | |||
| 1446 | p->rindex = ptr; | |||
| 1447 | } else | |||
| 1448 | return -EBADMSG74; | |||
| 1449 | } | |||
| 1450 | ||||
| 1451 | if (!GREEDY_REALLOC(ret, allocated, n + 1)greedy_realloc((void**) &(ret), &(allocated), (n + 1) , sizeof((ret)[0]))) | |||
| 1452 | return -ENOMEM12; | |||
| 1453 | ||||
| 1454 | ret[n] = 0; | |||
| 1455 | ||||
| 1456 | if (after_rindex != 0) | |||
| 1457 | p->rindex= after_rindex; | |||
| 1458 | ||||
| 1459 | *_ret = TAKE_PTR(ret)({ typeof(ret) _ptr_ = (ret); (ret) = ((void*)0); _ptr_; }); | |||
| 1460 | ||||
| 1461 | if (start) | |||
| 1462 | *start = rewinder.saved_rindex; | |||
| 1463 | CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0); | |||
| 1464 | ||||
| 1465 | return 0; | |||
| 1466 | } | |||
| 1467 | ||||
| 1468 | static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) { | |||
| 1469 | uint8_t window; | |||
| 1470 | uint8_t length; | |||
| 1471 | const uint8_t *bitmap; | |||
| 1472 | uint8_t bit = 0; | |||
| 1473 | unsigned i; | |||
| 1474 | bool_Bool found = false0; | |||
| 1475 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder; | |||
| 1476 | int r; | |||
| 1477 | ||||
| 1478 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1478, __PRETTY_FUNCTION__); } while (0); | |||
| 1479 | assert(types)do { if ((__builtin_expect(!!(!(types)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("types"), "../src/resolve/resolved-dns-packet.c" , 1479, __PRETTY_FUNCTION__); } while (0); | |||
| 1480 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 1481 | ||||
| 1482 | r = bitmap_ensure_allocated(types); | |||
| 1483 | if (r < 0) | |||
| 1484 | return r; | |||
| 1485 | ||||
| 1486 | r = dns_packet_read_uint8(p, &window, NULL((void*)0)); | |||
| 1487 | if (r < 0) | |||
| 1488 | return r; | |||
| 1489 | ||||
| 1490 | r = dns_packet_read_uint8(p, &length, NULL((void*)0)); | |||
| 1491 | if (r < 0) | |||
| 1492 | return r; | |||
| 1493 | ||||
| 1494 | if (length == 0 || length > 32) | |||
| 1495 | return -EBADMSG74; | |||
| 1496 | ||||
| 1497 | r = dns_packet_read(p, length, (const void **)&bitmap, NULL((void*)0)); | |||
| 1498 | if (r < 0) | |||
| 1499 | return r; | |||
| 1500 | ||||
| 1501 | for (i = 0; i < length; i++) { | |||
| 1502 | uint8_t bitmask = 1 << 7; | |||
| 1503 | ||||
| 1504 | if (!bitmap[i]) { | |||
| 1505 | found = false0; | |||
| 1506 | bit += 8; | |||
| 1507 | continue; | |||
| 1508 | } | |||
| 1509 | ||||
| 1510 | found = true1; | |||
| 1511 | ||||
| 1512 | for (; bitmask; bit++, bitmask >>= 1) | |||
| 1513 | if (bitmap[i] & bitmask) { | |||
| 1514 | uint16_t n; | |||
| 1515 | ||||
| 1516 | n = (uint16_t) window << 8 | (uint16_t) bit; | |||
| 1517 | ||||
| 1518 | /* Ignore pseudo-types. see RFC4034 section 4.1.2 */ | |||
| 1519 | if (dns_type_is_pseudo(n)) | |||
| 1520 | continue; | |||
| 1521 | ||||
| 1522 | r = bitmap_set(*types, n); | |||
| 1523 | if (r < 0) | |||
| 1524 | return r; | |||
| 1525 | } | |||
| 1526 | } | |||
| 1527 | ||||
| 1528 | if (!found) | |||
| 1529 | return -EBADMSG74; | |||
| 1530 | ||||
| 1531 | if (start) | |||
| 1532 | *start = rewinder.saved_rindex; | |||
| 1533 | CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0); | |||
| 1534 | ||||
| 1535 | return 0; | |||
| 1536 | } | |||
| 1537 | ||||
| 1538 | static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) { | |||
| 1539 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder; | |||
| 1540 | int r; | |||
| 1541 | ||||
| 1542 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 1543 | ||||
| 1544 | while (p->rindex < rewinder.saved_rindex + size) { | |||
| 1545 | r = dns_packet_read_type_window(p, types, NULL((void*)0)); | |||
| 1546 | if (r < 0) | |||
| 1547 | return r; | |||
| 1548 | ||||
| 1549 | /* don't read past end of current RR */ | |||
| 1550 | if (p->rindex > rewinder.saved_rindex + size) | |||
| 1551 | return -EBADMSG74; | |||
| 1552 | } | |||
| 1553 | ||||
| 1554 | if (p->rindex != rewinder.saved_rindex + size) | |||
| 1555 | return -EBADMSG74; | |||
| 1556 | ||||
| 1557 | if (start) | |||
| 1558 | *start = rewinder.saved_rindex; | |||
| 1559 | CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0); | |||
| 1560 | ||||
| 1561 | return 0; | |||
| 1562 | } | |||
| 1563 | ||||
| 1564 | int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool_Bool *ret_cache_flush, size_t *start) { | |||
| 1565 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder; | |||
| 1566 | _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0); | |||
| 1567 | bool_Bool cache_flush = false0; | |||
| 1568 | uint16_t class, type; | |||
| 1569 | DnsResourceKey *key; | |||
| 1570 | int r; | |||
| 1571 | ||||
| 1572 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1572, __PRETTY_FUNCTION__); } while (0); | |||
| 1573 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-packet.c" , 1573, __PRETTY_FUNCTION__); } while (0); | |||
| 1574 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 1575 | ||||
| 1576 | r = dns_packet_read_name(p, &name, true1, NULL((void*)0)); | |||
| 1577 | if (r < 0) | |||
| 1578 | return r; | |||
| 1579 | ||||
| 1580 | r = dns_packet_read_uint16(p, &type, NULL((void*)0)); | |||
| 1581 | if (r < 0) | |||
| 1582 | return r; | |||
| 1583 | ||||
| 1584 | r = dns_packet_read_uint16(p, &class, NULL((void*)0)); | |||
| 1585 | if (r < 0) | |||
| 1586 | return r; | |||
| 1587 | ||||
| 1588 | if (p->protocol == DNS_PROTOCOL_MDNS) { | |||
| 1589 | /* See RFC6762, Section 10.2 */ | |||
| 1590 | ||||
| 1591 | if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH(1 << 15))) { | |||
| 1592 | class &= ~MDNS_RR_CACHE_FLUSH(1 << 15); | |||
| 1593 | cache_flush = true1; | |||
| 1594 | } | |||
| 1595 | } | |||
| 1596 | ||||
| 1597 | key = dns_resource_key_new_consume(class, type, name); | |||
| 1598 | if (!key) | |||
| 1599 | return -ENOMEM12; | |||
| 1600 | ||||
| 1601 | name = NULL((void*)0); | |||
| 1602 | *ret = key; | |||
| 1603 | ||||
| 1604 | if (ret_cache_flush) | |||
| 1605 | *ret_cache_flush = cache_flush; | |||
| 1606 | if (start) | |||
| 1607 | *start = rewinder.saved_rindex; | |||
| 1608 | CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0); | |||
| 1609 | ||||
| 1610 | return 0; | |||
| 1611 | } | |||
| 1612 | ||||
| 1613 | static bool_Bool loc_size_ok(uint8_t size) { | |||
| 1614 | uint8_t m = size >> 4, e = size & 0xF; | |||
| 1615 | ||||
| 1616 | return m <= 9 && e <= 9 && (m > 0 || e == 0); | |||
| 1617 | } | |||
| 1618 | ||||
| 1619 | int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool_Bool *ret_cache_flush, size_t *start) { | |||
| 1620 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *rr = NULL((void*)0); | |||
| 1621 | _cleanup_(dns_resource_key_unrefp)__attribute__((cleanup(dns_resource_key_unrefp))) DnsResourceKey *key = NULL((void*)0); | |||
| 1622 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder; | |||
| 1623 | size_t offset; | |||
| 1624 | uint16_t rdlength; | |||
| 1625 | bool_Bool cache_flush; | |||
| 1626 | int r; | |||
| 1627 | ||||
| 1628 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 1628, __PRETTY_FUNCTION__); } while (0); | |||
| 1629 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-packet.c" , 1629, __PRETTY_FUNCTION__); } while (0); | |||
| 1630 | ||||
| 1631 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 1632 | ||||
| 1633 | r = dns_packet_read_key(p, &key, &cache_flush, NULL((void*)0)); | |||
| 1634 | if (r < 0) | |||
| 1635 | return r; | |||
| 1636 | ||||
| 1637 | if (!dns_class_is_valid_rr(key->class) || !dns_type_is_valid_rr(key->type)) | |||
| 1638 | return -EBADMSG74; | |||
| 1639 | ||||
| 1640 | rr = dns_resource_record_new(key); | |||
| 1641 | if (!rr) | |||
| 1642 | return -ENOMEM12; | |||
| 1643 | ||||
| 1644 | r = dns_packet_read_uint32(p, &rr->ttl, NULL((void*)0)); | |||
| 1645 | if (r < 0) | |||
| 1646 | return r; | |||
| 1647 | ||||
| 1648 | /* RFC 2181, Section 8, suggests to | |||
| 1649 | * treat a TTL with the MSB set as a zero TTL. */ | |||
| 1650 | if (rr->ttl & UINT32_C(0x80000000)0x80000000U) | |||
| 1651 | rr->ttl = 0; | |||
| 1652 | ||||
| 1653 | r = dns_packet_read_uint16(p, &rdlength, NULL((void*)0)); | |||
| 1654 | if (r < 0) | |||
| 1655 | return r; | |||
| 1656 | ||||
| 1657 | if (p->rindex + rdlength > p->size) | |||
| 1658 | return -EBADMSG74; | |||
| 1659 | ||||
| 1660 | offset = p->rindex; | |||
| 1661 | ||||
| 1662 | switch (rr->key->type) { | |||
| 1663 | ||||
| 1664 | case DNS_TYPE_SRV: | |||
| 1665 | r = dns_packet_read_uint16(p, &rr->srv.priority, NULL((void*)0)); | |||
| 1666 | if (r < 0) | |||
| 1667 | return r; | |||
| 1668 | r = dns_packet_read_uint16(p, &rr->srv.weight, NULL((void*)0)); | |||
| 1669 | if (r < 0) | |||
| 1670 | return r; | |||
| 1671 | r = dns_packet_read_uint16(p, &rr->srv.port, NULL((void*)0)); | |||
| 1672 | if (r < 0) | |||
| 1673 | return r; | |||
| 1674 | r = dns_packet_read_name(p, &rr->srv.name, true1, NULL((void*)0)); | |||
| 1675 | break; | |||
| 1676 | ||||
| 1677 | case DNS_TYPE_PTR: | |||
| 1678 | case DNS_TYPE_NS: | |||
| 1679 | case DNS_TYPE_CNAME: | |||
| 1680 | case DNS_TYPE_DNAME: | |||
| 1681 | r = dns_packet_read_name(p, &rr->ptr.name, true1, NULL((void*)0)); | |||
| 1682 | break; | |||
| 1683 | ||||
| 1684 | case DNS_TYPE_HINFO: | |||
| 1685 | r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL((void*)0)); | |||
| 1686 | if (r < 0) | |||
| 1687 | return r; | |||
| 1688 | ||||
| 1689 | r = dns_packet_read_string(p, &rr->hinfo.os, NULL((void*)0)); | |||
| 1690 | break; | |||
| 1691 | ||||
| 1692 | case DNS_TYPE_SPF: /* exactly the same as TXT */ | |||
| 1693 | case DNS_TYPE_TXT: | |||
| 1694 | if (rdlength <= 0) { | |||
| 1695 | r = dns_txt_item_new_empty(&rr->txt.items); | |||
| 1696 | if (r < 0) | |||
| 1697 | return r; | |||
| 1698 | } else { | |||
| 1699 | DnsTxtItem *last = NULL((void*)0); | |||
| 1700 | ||||
| 1701 | while (p->rindex < offset + rdlength) { | |||
| 1702 | DnsTxtItem *i; | |||
| 1703 | const void *data; | |||
| 1704 | size_t sz; | |||
| 1705 | ||||
| 1706 | r = dns_packet_read_raw_string(p, &data, &sz, NULL((void*)0)); | |||
| 1707 | if (r < 0) | |||
| 1708 | return r; | |||
| 1709 | ||||
| 1710 | i = malloc0(offsetof(DnsTxtItem, data) + sz + 1)(calloc(1, (__builtin_offsetof(DnsTxtItem, data) + sz + 1))); /* extra NUL byte at the end */ | |||
| 1711 | if (!i) | |||
| 1712 | return -ENOMEM12; | |||
| 1713 | ||||
| 1714 | memcpy(i->data, data, sz); | |||
| 1715 | i->length = sz; | |||
| 1716 | ||||
| 1717 | LIST_INSERT_AFTER(items, rr->txt.items, last, i)do { typeof(*(rr->txt.items)) **_head = &(rr->txt.items ), *_a = (last), *_b = (i); do { if ((__builtin_expect(!!(!(_b )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_b"), "../src/resolve/resolved-dns-packet.c" , 1717, __PRETTY_FUNCTION__); } while (0); if (!_a) { if ((_b ->items_next = *_head)) _b->items_next->items_prev = _b; _b->items_prev = ((void*)0); *_head = _b; } else { if ((_b->items_next = _a->items_next)) _b->items_next-> items_prev = _b; _b->items_prev = _a; _a->items_next = _b ; } } while (0); | |||
| 1718 | last = i; | |||
| 1719 | } | |||
| 1720 | } | |||
| 1721 | ||||
| 1722 | r = 0; | |||
| 1723 | break; | |||
| 1724 | ||||
| 1725 | case DNS_TYPE_A: | |||
| 1726 | r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL((void*)0)); | |||
| 1727 | break; | |||
| 1728 | ||||
| 1729 | case DNS_TYPE_AAAA: | |||
| 1730 | r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL((void*)0)); | |||
| 1731 | break; | |||
| 1732 | ||||
| 1733 | case DNS_TYPE_SOA: | |||
| 1734 | r = dns_packet_read_name(p, &rr->soa.mname, true1, NULL((void*)0)); | |||
| 1735 | if (r < 0) | |||
| 1736 | return r; | |||
| 1737 | ||||
| 1738 | r = dns_packet_read_name(p, &rr->soa.rname, true1, NULL((void*)0)); | |||
| 1739 | if (r < 0) | |||
| 1740 | return r; | |||
| 1741 | ||||
| 1742 | r = dns_packet_read_uint32(p, &rr->soa.serial, NULL((void*)0)); | |||
| 1743 | if (r < 0) | |||
| 1744 | return r; | |||
| 1745 | ||||
| 1746 | r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL((void*)0)); | |||
| 1747 | if (r < 0) | |||
| 1748 | return r; | |||
| 1749 | ||||
| 1750 | r = dns_packet_read_uint32(p, &rr->soa.retry, NULL((void*)0)); | |||
| 1751 | if (r < 0) | |||
| 1752 | return r; | |||
| 1753 | ||||
| 1754 | r = dns_packet_read_uint32(p, &rr->soa.expire, NULL((void*)0)); | |||
| 1755 | if (r < 0) | |||
| 1756 | return r; | |||
| 1757 | ||||
| 1758 | r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL((void*)0)); | |||
| 1759 | break; | |||
| 1760 | ||||
| 1761 | case DNS_TYPE_MX: | |||
| 1762 | r = dns_packet_read_uint16(p, &rr->mx.priority, NULL((void*)0)); | |||
| 1763 | if (r < 0) | |||
| 1764 | return r; | |||
| 1765 | ||||
| 1766 | r = dns_packet_read_name(p, &rr->mx.exchange, true1, NULL((void*)0)); | |||
| 1767 | break; | |||
| 1768 | ||||
| 1769 | case DNS_TYPE_LOC: { | |||
| 1770 | uint8_t t; | |||
| 1771 | size_t pos; | |||
| 1772 | ||||
| 1773 | r = dns_packet_read_uint8(p, &t, &pos); | |||
| 1774 | if (r < 0) | |||
| 1775 | return r; | |||
| 1776 | ||||
| 1777 | if (t == 0) { | |||
| 1778 | rr->loc.version = t; | |||
| 1779 | ||||
| 1780 | r = dns_packet_read_uint8(p, &rr->loc.size, NULL((void*)0)); | |||
| 1781 | if (r < 0) | |||
| 1782 | return r; | |||
| 1783 | ||||
| 1784 | if (!loc_size_ok(rr->loc.size)) | |||
| 1785 | return -EBADMSG74; | |||
| 1786 | ||||
| 1787 | r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL((void*)0)); | |||
| 1788 | if (r < 0) | |||
| 1789 | return r; | |||
| 1790 | ||||
| 1791 | if (!loc_size_ok(rr->loc.horiz_pre)) | |||
| 1792 | return -EBADMSG74; | |||
| 1793 | ||||
| 1794 | r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL((void*)0)); | |||
| 1795 | if (r < 0) | |||
| 1796 | return r; | |||
| 1797 | ||||
| 1798 | if (!loc_size_ok(rr->loc.vert_pre)) | |||
| 1799 | return -EBADMSG74; | |||
| 1800 | ||||
| 1801 | r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL((void*)0)); | |||
| 1802 | if (r < 0) | |||
| 1803 | return r; | |||
| 1804 | ||||
| 1805 | r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL((void*)0)); | |||
| 1806 | if (r < 0) | |||
| 1807 | return r; | |||
| 1808 | ||||
| 1809 | r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL((void*)0)); | |||
| 1810 | if (r < 0) | |||
| 1811 | return r; | |||
| 1812 | ||||
| 1813 | break; | |||
| 1814 | } else { | |||
| 1815 | dns_packet_rewind(p, pos); | |||
| 1816 | rr->unparseable = true1; | |||
| 1817 | goto unparseable; | |||
| 1818 | } | |||
| 1819 | } | |||
| 1820 | ||||
| 1821 | case DNS_TYPE_DS: | |||
| 1822 | r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL((void*)0)); | |||
| 1823 | if (r < 0) | |||
| 1824 | return r; | |||
| 1825 | ||||
| 1826 | r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL((void*)0)); | |||
| 1827 | if (r < 0) | |||
| 1828 | return r; | |||
| 1829 | ||||
| 1830 | r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL((void*)0)); | |||
| 1831 | if (r < 0) | |||
| 1832 | return r; | |||
| 1833 | ||||
| 1834 | if (rdlength < 4) | |||
| 1835 | return -EBADMSG74; | |||
| 1836 | ||||
| 1837 | r = dns_packet_read_memdup(p, rdlength - 4, | |||
| 1838 | &rr->ds.digest, &rr->ds.digest_size, | |||
| 1839 | NULL((void*)0)); | |||
| 1840 | if (r < 0) | |||
| 1841 | return r; | |||
| 1842 | ||||
| 1843 | if (rr->ds.digest_size <= 0) | |||
| 1844 | /* the accepted size depends on the algorithm, but for now | |||
| 1845 | just ensure that the value is greater than zero */ | |||
| 1846 | return -EBADMSG74; | |||
| 1847 | ||||
| 1848 | break; | |||
| 1849 | ||||
| 1850 | case DNS_TYPE_SSHFP: | |||
| 1851 | r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL((void*)0)); | |||
| 1852 | if (r < 0) | |||
| 1853 | return r; | |||
| 1854 | ||||
| 1855 | r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL((void*)0)); | |||
| 1856 | if (r < 0) | |||
| 1857 | return r; | |||
| 1858 | ||||
| 1859 | if (rdlength < 2) | |||
| 1860 | return -EBADMSG74; | |||
| 1861 | ||||
| 1862 | r = dns_packet_read_memdup(p, rdlength - 2, | |||
| 1863 | &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size, | |||
| 1864 | NULL((void*)0)); | |||
| 1865 | ||||
| 1866 | if (rr->sshfp.fingerprint_size <= 0) | |||
| 1867 | /* the accepted size depends on the algorithm, but for now | |||
| 1868 | just ensure that the value is greater than zero */ | |||
| 1869 | return -EBADMSG74; | |||
| 1870 | ||||
| 1871 | break; | |||
| 1872 | ||||
| 1873 | case DNS_TYPE_DNSKEY: | |||
| 1874 | r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL((void*)0)); | |||
| 1875 | if (r < 0) | |||
| 1876 | return r; | |||
| 1877 | ||||
| 1878 | r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL((void*)0)); | |||
| 1879 | if (r < 0) | |||
| 1880 | return r; | |||
| 1881 | ||||
| 1882 | r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL((void*)0)); | |||
| 1883 | if (r < 0) | |||
| 1884 | return r; | |||
| 1885 | ||||
| 1886 | if (rdlength < 4) | |||
| 1887 | return -EBADMSG74; | |||
| 1888 | ||||
| 1889 | r = dns_packet_read_memdup(p, rdlength - 4, | |||
| 1890 | &rr->dnskey.key, &rr->dnskey.key_size, | |||
| 1891 | NULL((void*)0)); | |||
| 1892 | ||||
| 1893 | if (rr->dnskey.key_size <= 0) | |||
| 1894 | /* the accepted size depends on the algorithm, but for now | |||
| 1895 | just ensure that the value is greater than zero */ | |||
| 1896 | return -EBADMSG74; | |||
| 1897 | ||||
| 1898 | break; | |||
| 1899 | ||||
| 1900 | case DNS_TYPE_RRSIG: | |||
| 1901 | r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL((void*)0)); | |||
| 1902 | if (r < 0) | |||
| 1903 | return r; | |||
| 1904 | ||||
| 1905 | r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL((void*)0)); | |||
| 1906 | if (r < 0) | |||
| 1907 | return r; | |||
| 1908 | ||||
| 1909 | r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL((void*)0)); | |||
| 1910 | if (r < 0) | |||
| 1911 | return r; | |||
| 1912 | ||||
| 1913 | r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL((void*)0)); | |||
| 1914 | if (r < 0) | |||
| 1915 | return r; | |||
| 1916 | ||||
| 1917 | r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL((void*)0)); | |||
| 1918 | if (r < 0) | |||
| 1919 | return r; | |||
| 1920 | ||||
| 1921 | r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL((void*)0)); | |||
| 1922 | if (r < 0) | |||
| 1923 | return r; | |||
| 1924 | ||||
| 1925 | r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL((void*)0)); | |||
| 1926 | if (r < 0) | |||
| 1927 | return r; | |||
| 1928 | ||||
| 1929 | r = dns_packet_read_name(p, &rr->rrsig.signer, false0, NULL((void*)0)); | |||
| 1930 | if (r < 0) | |||
| 1931 | return r; | |||
| 1932 | ||||
| 1933 | if (rdlength + offset < p->rindex) | |||
| 1934 | return -EBADMSG74; | |||
| 1935 | ||||
| 1936 | r = dns_packet_read_memdup(p, offset + rdlength - p->rindex, | |||
| 1937 | &rr->rrsig.signature, &rr->rrsig.signature_size, | |||
| 1938 | NULL((void*)0)); | |||
| 1939 | ||||
| 1940 | if (rr->rrsig.signature_size <= 0) | |||
| 1941 | /* the accepted size depends on the algorithm, but for now | |||
| 1942 | just ensure that the value is greater than zero */ | |||
| 1943 | return -EBADMSG74; | |||
| 1944 | ||||
| 1945 | break; | |||
| 1946 | ||||
| 1947 | case DNS_TYPE_NSEC: { | |||
| 1948 | ||||
| 1949 | /* | |||
| 1950 | * RFC6762, section 18.14 explictly states mDNS should use name compression. | |||
| 1951 | * This contradicts RFC3845, section 2.1.1 | |||
| 1952 | */ | |||
| 1953 | ||||
| 1954 | bool_Bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS; | |||
| 1955 | ||||
| 1956 | r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL((void*)0)); | |||
| 1957 | if (r < 0) | |||
| 1958 | return r; | |||
| 1959 | ||||
| 1960 | r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL((void*)0)); | |||
| 1961 | ||||
| 1962 | /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself | |||
| 1963 | * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records | |||
| 1964 | * without the NSEC bit set. */ | |||
| 1965 | ||||
| 1966 | break; | |||
| 1967 | } | |||
| 1968 | case DNS_TYPE_NSEC3: { | |||
| 1969 | uint8_t size; | |||
| 1970 | ||||
| 1971 | r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL((void*)0)); | |||
| 1972 | if (r < 0) | |||
| 1973 | return r; | |||
| 1974 | ||||
| 1975 | r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL((void*)0)); | |||
| 1976 | if (r < 0) | |||
| 1977 | return r; | |||
| 1978 | ||||
| 1979 | r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL((void*)0)); | |||
| 1980 | if (r < 0) | |||
| 1981 | return r; | |||
| 1982 | ||||
| 1983 | /* this may be zero */ | |||
| 1984 | r = dns_packet_read_uint8(p, &size, NULL((void*)0)); | |||
| 1985 | if (r < 0) | |||
| 1986 | return r; | |||
| 1987 | ||||
| 1988 | r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL((void*)0)); | |||
| 1989 | if (r < 0) | |||
| 1990 | return r; | |||
| 1991 | ||||
| 1992 | r = dns_packet_read_uint8(p, &size, NULL((void*)0)); | |||
| 1993 | if (r < 0) | |||
| 1994 | return r; | |||
| 1995 | ||||
| 1996 | if (size <= 0) | |||
| 1997 | return -EBADMSG74; | |||
| 1998 | ||||
| 1999 | r = dns_packet_read_memdup(p, size, | |||
| 2000 | &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, | |||
| 2001 | NULL((void*)0)); | |||
| 2002 | if (r < 0) | |||
| 2003 | return r; | |||
| 2004 | ||||
| 2005 | r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL((void*)0)); | |||
| 2006 | ||||
| 2007 | /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */ | |||
| 2008 | ||||
| 2009 | break; | |||
| 2010 | } | |||
| 2011 | ||||
| 2012 | case DNS_TYPE_TLSA: | |||
| 2013 | r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL((void*)0)); | |||
| 2014 | if (r < 0) | |||
| 2015 | return r; | |||
| 2016 | ||||
| 2017 | r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL((void*)0)); | |||
| 2018 | if (r < 0) | |||
| 2019 | return r; | |||
| 2020 | ||||
| 2021 | r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL((void*)0)); | |||
| 2022 | if (r < 0) | |||
| 2023 | return r; | |||
| 2024 | ||||
| 2025 | if (rdlength < 3) | |||
| 2026 | return -EBADMSG74; | |||
| 2027 | ||||
| 2028 | r = dns_packet_read_memdup(p, rdlength - 3, | |||
| 2029 | &rr->tlsa.data, &rr->tlsa.data_size, | |||
| 2030 | NULL((void*)0)); | |||
| 2031 | ||||
| 2032 | if (rr->tlsa.data_size <= 0) | |||
| 2033 | /* the accepted size depends on the algorithm, but for now | |||
| 2034 | just ensure that the value is greater than zero */ | |||
| 2035 | return -EBADMSG74; | |||
| 2036 | ||||
| 2037 | break; | |||
| 2038 | ||||
| 2039 | case DNS_TYPE_CAA: | |||
| 2040 | r = dns_packet_read_uint8(p, &rr->caa.flags, NULL((void*)0)); | |||
| 2041 | if (r < 0) | |||
| 2042 | return r; | |||
| 2043 | ||||
| 2044 | r = dns_packet_read_string(p, &rr->caa.tag, NULL((void*)0)); | |||
| 2045 | if (r < 0) | |||
| 2046 | return r; | |||
| 2047 | ||||
| 2048 | if (rdlength + offset < p->rindex) | |||
| 2049 | return -EBADMSG74; | |||
| 2050 | ||||
| 2051 | r = dns_packet_read_memdup(p, | |||
| 2052 | rdlength + offset - p->rindex, | |||
| 2053 | &rr->caa.value, &rr->caa.value_size, NULL((void*)0)); | |||
| 2054 | ||||
| 2055 | break; | |||
| 2056 | ||||
| 2057 | case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */ | |||
| 2058 | case DNS_TYPE_OPENPGPKEY: | |||
| 2059 | default: | |||
| 2060 | unparseable: | |||
| 2061 | r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL((void*)0)); | |||
| 2062 | ||||
| 2063 | break; | |||
| 2064 | } | |||
| 2065 | if (r < 0) | |||
| 2066 | return r; | |||
| 2067 | if (p->rindex != offset + rdlength) | |||
| 2068 | return -EBADMSG74; | |||
| 2069 | ||||
| 2070 | *ret = TAKE_PTR(rr)({ typeof(rr) _ptr_ = (rr); (rr) = ((void*)0); _ptr_; }); | |||
| 2071 | ||||
| 2072 | if (ret_cache_flush) | |||
| 2073 | *ret_cache_flush = cache_flush; | |||
| 2074 | if (start) | |||
| 2075 | *start = rewinder.saved_rindex; | |||
| 2076 | CANCEL_REWINDER(rewinder)do { rewinder.packet = ((void*)0); } while (0); | |||
| 2077 | ||||
| 2078 | return 0; | |||
| 2079 | } | |||
| 2080 | ||||
| 2081 | static bool_Bool opt_is_good(DnsResourceRecord *rr, bool_Bool *rfc6975) { | |||
| 2082 | const uint8_t* p; | |||
| 2083 | bool_Bool found_dau_dhu_n3u = false0; | |||
| 2084 | size_t l; | |||
| 2085 | ||||
| 2086 | /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in | |||
| 2087 | * a reply). */ | |||
| 2088 | ||||
| 2089 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-packet.c" , 2089, __PRETTY_FUNCTION__); } while (0); | |||
| 2090 | assert(rr->key->type == DNS_TYPE_OPT)do { if ((__builtin_expect(!!(!(rr->key->type == DNS_TYPE_OPT )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("rr->key->type == DNS_TYPE_OPT" ), "../src/resolve/resolved-dns-packet.c", 2090, __PRETTY_FUNCTION__ ); } while (0); | |||
| 2091 | ||||
| 2092 | /* Check that the version is 0 */ | |||
| 2093 | if (((rr->ttl >> 16) & UINT32_C(0xFF)0xFFU) != 0) { | |||
| 2094 | *rfc6975 = false0; | |||
| 2095 | return true1; /* if it's not version 0, it's OK, but we will ignore the OPT field contents */ | |||
| 2096 | } | |||
| 2097 | ||||
| 2098 | p = rr->opt.data; | |||
| 2099 | l = rr->opt.data_size; | |||
| 2100 | while (l > 0) { | |||
| 2101 | uint16_t option_code, option_length; | |||
| 2102 | ||||
| 2103 | /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */ | |||
| 2104 | if (l < 4U) | |||
| 2105 | return false0; | |||
| 2106 | ||||
| 2107 | option_code = unaligned_read_be16(p); | |||
| 2108 | option_length = unaligned_read_be16(p + 2); | |||
| 2109 | ||||
| 2110 | if (l < option_length + 4U) | |||
| 2111 | return false0; | |||
| 2112 | ||||
| 2113 | /* RFC 6975 DAU, DHU or N3U fields found. */ | |||
| 2114 | if (IN_SET(option_code, 5, 6, 7)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){5, 6, 7})/sizeof(int)]; switch(option_code ) { case 5: case 6: case 7: _found = 1; break; default: break ; } _found; })) | |||
| 2115 | found_dau_dhu_n3u = true1; | |||
| 2116 | ||||
| 2117 | p += option_length + 4U; | |||
| 2118 | l -= option_length + 4U; | |||
| 2119 | } | |||
| 2120 | ||||
| 2121 | *rfc6975 = found_dau_dhu_n3u; | |||
| 2122 | return true1; | |||
| 2123 | } | |||
| 2124 | ||||
| 2125 | static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question) { | |||
| 2126 | _cleanup_(dns_question_unrefp)__attribute__((cleanup(dns_question_unrefp))) DnsQuestion *question = NULL((void*)0); | |||
| 2127 | unsigned n, i; | |||
| 2128 | int r; | |||
| 2129 | ||||
| 2130 | n = DNS_PACKET_QDCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->qdcount); | |||
| 2131 | if (n > 0) { | |||
| 2132 | question = dns_question_new(n); | |||
| 2133 | if (!question) | |||
| 2134 | return -ENOMEM12; | |||
| 2135 | ||||
| 2136 | for (i = 0; i < n; i++) { | |||
| 2137 | _cleanup_(dns_resource_key_unrefp)__attribute__((cleanup(dns_resource_key_unrefp))) DnsResourceKey *key = NULL((void*)0); | |||
| 2138 | bool_Bool cache_flush; | |||
| 2139 | ||||
| 2140 | r = dns_packet_read_key(p, &key, &cache_flush, NULL((void*)0)); | |||
| 2141 | if (r < 0) | |||
| 2142 | return r; | |||
| 2143 | ||||
| 2144 | if (cache_flush) | |||
| 2145 | return -EBADMSG74; | |||
| 2146 | ||||
| 2147 | if (!dns_type_is_valid_query(key->type)) | |||
| 2148 | return -EBADMSG74; | |||
| 2149 | ||||
| 2150 | r = dns_question_add(question, key); | |||
| 2151 | if (r < 0) | |||
| 2152 | return r; | |||
| 2153 | } | |||
| 2154 | } | |||
| 2155 | ||||
| 2156 | *ret_question = TAKE_PTR(question)({ typeof(question) _ptr_ = (question); (question) = ((void*) 0); _ptr_; }); | |||
| 2157 | ||||
| 2158 | return 0; | |||
| 2159 | } | |||
| 2160 | ||||
| 2161 | static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) { | |||
| 2162 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *answer = NULL((void*)0); | |||
| 2163 | unsigned n, i; | |||
| 2164 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *previous = NULL((void*)0); | |||
| 2165 | bool_Bool bad_opt = false0; | |||
| 2166 | int r; | |||
| 2167 | ||||
| 2168 | n = DNS_PACKET_RRCOUNT(p); | |||
| 2169 | if (n == 0) | |||
| 2170 | return 0; | |||
| 2171 | ||||
| 2172 | answer = dns_answer_new(n); | |||
| 2173 | if (!answer) | |||
| 2174 | return -ENOMEM12; | |||
| 2175 | ||||
| 2176 | for (i = 0; i < n; i++) { | |||
| 2177 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *rr = NULL((void*)0); | |||
| 2178 | bool_Bool cache_flush = false0; | |||
| 2179 | ||||
| 2180 | r = dns_packet_read_rr(p, &rr, &cache_flush, NULL((void*)0)); | |||
| 2181 | if (r < 0) | |||
| 2182 | return r; | |||
| 2183 | ||||
| 2184 | /* Try to reduce memory usage a bit */ | |||
| 2185 | if (previous) | |||
| 2186 | dns_resource_key_reduce(&rr->key, &previous->key); | |||
| 2187 | ||||
| 2188 | if (rr->key->type == DNS_TYPE_OPT) { | |||
| 2189 | bool_Bool has_rfc6975; | |||
| 2190 | ||||
| 2191 | if (p->opt || bad_opt) { | |||
| 2192 | /* Multiple OPT RRs? if so, let's ignore all, because there's | |||
| 2193 | * something wrong with the server, and if one is valid we wouldn't | |||
| 2194 | * know which one. */ | |||
| 2195 | log_debug("Multiple OPT RRs detected, ignoring all.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-dns-packet.c", 2195, __func__, "Multiple OPT RRs detected, ignoring all." ) : -abs(_e); }); | |||
| 2196 | bad_opt = true1; | |||
| 2197 | continue; | |||
| 2198 | } | |||
| 2199 | ||||
| 2200 | if (!dns_name_is_root(dns_resource_key_name(rr->key))) { | |||
| 2201 | /* If the OPT RR is not owned by the root domain, then it is bad, | |||
| 2202 | * let's ignore it. */ | |||
| 2203 | log_debug("OPT RR is not owned by root domain, ignoring.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-dns-packet.c", 2203, __func__, "OPT RR is not owned by root domain, ignoring." ) : -abs(_e); }); | |||
| 2204 | bad_opt = true1; | |||
| 2205 | continue; | |||
| 2206 | } | |||
| 2207 | ||||
| 2208 | if (i < DNS_PACKET_ANCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->ancount) + DNS_PACKET_NSCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->nscount)) { | |||
| 2209 | /* OPT RR is in the wrong section? Some Belkin routers do this. This | |||
| 2210 | * is a hint the EDNS implementation is borked, like the Belkin one | |||
| 2211 | * is, hence ignore it. */ | |||
| 2212 | log_debug("OPT RR in wrong section, ignoring.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-dns-packet.c", 2212, __func__, "OPT RR in wrong section, ignoring." ) : -abs(_e); }); | |||
| 2213 | bad_opt = true1; | |||
| 2214 | continue; | |||
| 2215 | } | |||
| 2216 | ||||
| 2217 | if (!opt_is_good(rr, &has_rfc6975)) { | |||
| 2218 | log_debug("Malformed OPT RR, ignoring.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-dns-packet.c", 2218, __func__, "Malformed OPT RR, ignoring." ) : -abs(_e); }); | |||
| 2219 | bad_opt = true1; | |||
| 2220 | continue; | |||
| 2221 | } | |||
| 2222 | ||||
| 2223 | if (DNS_PACKET_QR(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 15) & 1)) { | |||
| 2224 | /* Additional checks for responses */ | |||
| 2225 | ||||
| 2226 | if (!DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(rr)) { | |||
| 2227 | /* If this is a reply and we don't know the EDNS version | |||
| 2228 | * then something is weird... */ | |||
| 2229 | log_debug("EDNS version newer that our request, bad server.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-dns-packet.c", 2229, __func__, "EDNS version newer that our request, bad server." ) : -abs(_e); }); | |||
| 2230 | return -EBADMSG74; | |||
| 2231 | } | |||
| 2232 | ||||
| 2233 | if (has_rfc6975) { | |||
| 2234 | /* If the OPT RR contains RFC6975 algorithm data, then this | |||
| 2235 | * is indication that the server just copied the OPT it got | |||
| 2236 | * from us (which contained that data) back into the reply. | |||
| 2237 | * If so, then it doesn't properly support EDNS, as RFC6975 | |||
| 2238 | * makes it very clear that the algorithm data should only | |||
| 2239 | * be contained in questions, never in replies. Crappy | |||
| 2240 | * Belkin routers copy the OPT data for example, hence let's | |||
| 2241 | * detect this so that we downgrade early. */ | |||
| 2242 | log_debug("OPT RR contained RFC6975 data, ignoring.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/resolve/resolved-dns-packet.c", 2242, __func__, "OPT RR contained RFC6975 data, ignoring." ) : -abs(_e); }); | |||
| 2243 | bad_opt = true1; | |||
| 2244 | continue; | |||
| 2245 | } | |||
| 2246 | } | |||
| 2247 | ||||
| 2248 | p->opt = dns_resource_record_ref(rr); | |||
| 2249 | } else { | |||
| 2250 | /* According to RFC 4795, section 2.9. only the RRs from the Answer section | |||
| 2251 | * shall be cached. Hence mark only those RRs as cacheable by default, but | |||
| 2252 | * not the ones from the Additional or Authority sections. */ | |||
| 2253 | DnsAnswerFlags flags = | |||
| 2254 | (i < DNS_PACKET_ANCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->ancount) ? DNS_ANSWER_CACHEABLE : 0) | | |||
| 2255 | (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0); | |||
| 2256 | ||||
| 2257 | r = dns_answer_add(answer, rr, p->ifindex, flags); | |||
| 2258 | if (r < 0) | |||
| 2259 | return r; | |||
| 2260 | } | |||
| 2261 | ||||
| 2262 | /* Remember this RR, so that we potentically can merge it's ->key object with the | |||
| 2263 | * next RR. Note that we only do this if we actually decided to keep the RR around. | |||
| 2264 | */ | |||
| 2265 | dns_resource_record_unref(previous); | |||
| 2266 | previous = dns_resource_record_ref(rr); | |||
| 2267 | } | |||
| 2268 | ||||
| 2269 | if (bad_opt) | |||
| 2270 | p->opt = dns_resource_record_unref(p->opt); | |||
| 2271 | ||||
| 2272 | *ret_answer = TAKE_PTR(answer)({ typeof(answer) _ptr_ = (answer); (answer) = ((void*)0); _ptr_ ; }); | |||
| 2273 | ||||
| 2274 | return 0; | |||
| 2275 | } | |||
| 2276 | ||||
| 2277 | int dns_packet_extract(DnsPacket *p) { | |||
| 2278 | _cleanup_(dns_question_unrefp)__attribute__((cleanup(dns_question_unrefp))) DnsQuestion *question = NULL((void*)0); | |||
| 2279 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *answer = NULL((void*)0); | |||
| 2280 | _cleanup_(rewind_dns_packet)__attribute__((cleanup(rewind_dns_packet))) DnsPacketRewinder rewinder = {}; | |||
| 2281 | int r; | |||
| 2282 | ||||
| 2283 | if (p->extracted) | |||
| 2284 | return 0; | |||
| 2285 | ||||
| 2286 | INIT_REWINDER(rewinder, p)do { rewinder.packet = p; rewinder.saved_rindex = p->rindex ; } while (0); | |||
| 2287 | dns_packet_rewind(p, DNS_PACKET_HEADER_SIZEsizeof(DnsPacketHeader)); | |||
| 2288 | ||||
| 2289 | r = dns_packet_extract_question(p, &question); | |||
| 2290 | if (r < 0) | |||
| 2291 | return r; | |||
| 2292 | ||||
| 2293 | r = dns_packet_extract_answer(p, &answer); | |||
| 2294 | if (r < 0) | |||
| 2295 | return r; | |||
| 2296 | ||||
| 2297 | p->question = TAKE_PTR(question)({ typeof(question) _ptr_ = (question); (question) = ((void*) 0); _ptr_; }); | |||
| 2298 | p->answer = TAKE_PTR(answer)({ typeof(answer) _ptr_ = (answer); (answer) = ((void*)0); _ptr_ ; }); | |||
| 2299 | ||||
| 2300 | p->extracted = true1; | |||
| 2301 | ||||
| 2302 | /* no CANCEL, always rewind */ | |||
| 2303 | return 0; | |||
| 2304 | } | |||
| 2305 | ||||
| 2306 | int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) { | |||
| 2307 | int r; | |||
| 2308 | ||||
| 2309 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-dns-packet.c" , 2309, __PRETTY_FUNCTION__); } while (0); | |||
| 2310 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-packet.c" , 2310, __PRETTY_FUNCTION__); } while (0); | |||
| 2311 | ||||
| 2312 | /* Checks if the specified packet is a reply for the specified | |||
| 2313 | * key and the specified key is the only one in the question | |||
| 2314 | * section. */ | |||
| 2315 | ||||
| 2316 | if (DNS_PACKET_QR(p)((be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->flags) >> 15) & 1) != 1) | |||
| 2317 | return 0; | |||
| 2318 | ||||
| 2319 | /* Let's unpack the packet, if that hasn't happened yet. */ | |||
| 2320 | r = dns_packet_extract(p); | |||
| 2321 | if (r < 0) | |||
| 2322 | return r; | |||
| 2323 | ||||
| 2324 | if (!p->question) | |||
| 2325 | return 0; | |||
| 2326 | ||||
| 2327 | if (p->question->n_keys != 1) | |||
| 2328 | return 0; | |||
| 2329 | ||||
| 2330 | return dns_resource_key_equal(p->question->keys[0], key); | |||
| 2331 | } | |||
| 2332 | ||||
| 2333 | static void dns_packet_hash_func(const void *p, struct siphash *state) { | |||
| 2334 | const DnsPacket *s = p; | |||
| 2335 | ||||
| 2336 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/resolve/resolved-dns-packet.c" , 2336, __PRETTY_FUNCTION__); } while (0); | |||
| 2337 | ||||
| 2338 | siphash24_compress(&s->size, sizeof(s->size), state); | |||
| 2339 | siphash24_compress(DNS_PACKET_DATA((DnsPacket*) s), s->size, state); | |||
| 2340 | } | |||
| 2341 | ||||
| 2342 | static int dns_packet_compare_func(const void *a, const void *b) { | |||
| 2343 | const DnsPacket *x = a, *y = b; | |||
| 2344 | ||||
| 2345 | if (x->size < y->size) | |||
| 2346 | return -1; | |||
| 2347 | if (x->size > y->size) | |||
| 2348 | return 1; | |||
| 2349 | ||||
| 2350 | return memcmp(DNS_PACKET_DATA((DnsPacket*) x), DNS_PACKET_DATA((DnsPacket*) y), x->size); | |||
| 2351 | } | |||
| 2352 | ||||
| 2353 | const struct hash_ops dns_packet_hash_ops = { | |||
| 2354 | .hash = dns_packet_hash_func, | |||
| 2355 | .compare = dns_packet_compare_func | |||
| 2356 | }; | |||
| 2357 | ||||
| 2358 | static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = { | |||
| 2359 | [DNS_RCODE_SUCCESS] = "SUCCESS", | |||
| 2360 | [DNS_RCODE_FORMERR] = "FORMERR", | |||
| 2361 | [DNS_RCODE_SERVFAIL] = "SERVFAIL", | |||
| 2362 | [DNS_RCODE_NXDOMAIN] = "NXDOMAIN", | |||
| 2363 | [DNS_RCODE_NOTIMP] = "NOTIMP", | |||
| 2364 | [DNS_RCODE_REFUSED] = "REFUSED", | |||
| 2365 | [DNS_RCODE_YXDOMAIN] = "YXDOMAIN", | |||
| 2366 | [DNS_RCODE_YXRRSET] = "YRRSET", | |||
| 2367 | [DNS_RCODE_NXRRSET] = "NXRRSET", | |||
| 2368 | [DNS_RCODE_NOTAUTH] = "NOTAUTH", | |||
| 2369 | [DNS_RCODE_NOTZONE] = "NOTZONE", | |||
| 2370 | [DNS_RCODE_BADVERS] = "BADVERS", | |||
| 2371 | [DNS_RCODE_BADKEY] = "BADKEY", | |||
| 2372 | [DNS_RCODE_BADTIME] = "BADTIME", | |||
| 2373 | [DNS_RCODE_BADMODE] = "BADMODE", | |||
| 2374 | [DNS_RCODE_BADNAME] = "BADNAME", | |||
| 2375 | [DNS_RCODE_BADALG] = "BADALG", | |||
| 2376 | [DNS_RCODE_BADTRUNC] = "BADTRUNC", | |||
| 2377 | [DNS_RCODE_BADCOOKIE] = "BADCOOKIE", | |||
| 2378 | }; | |||
| 2379 | DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int)const char *dns_rcode_to_string(int i) { if (i < 0 || i >= (int) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(dns_rcode_table), typeof(&*(dns_rcode_table))), sizeof (dns_rcode_table)/sizeof((dns_rcode_table)[0]), ((void)0)))) return ((void*)0); return dns_rcode_table[i]; } int dns_rcode_from_string (const char *s) { return (int) string_table_lookup(dns_rcode_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(dns_rcode_table), typeof(&*(dns_rcode_table))), sizeof (dns_rcode_table)/sizeof((dns_rcode_table)[0]), ((void)0))), s ); }; | |||
| 2380 | ||||
| 2381 | static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = { | |||
| 2382 | [DNS_PROTOCOL_DNS] = "dns", | |||
| 2383 | [DNS_PROTOCOL_MDNS] = "mdns", | |||
| 2384 | [DNS_PROTOCOL_LLMNR] = "llmnr", | |||
| 2385 | }; | |||
| 2386 | DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol)const char *dns_protocol_to_string(DnsProtocol i) { if (i < 0 || i >= (DnsProtocol) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(dns_protocol_table), typeof (&*(dns_protocol_table))), sizeof(dns_protocol_table)/sizeof ((dns_protocol_table)[0]), ((void)0)))) return ((void*)0); return dns_protocol_table[i]; } DnsProtocol dns_protocol_from_string (const char *s) { return (DnsProtocol) string_table_lookup(dns_protocol_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(dns_protocol_table), typeof(&*(dns_protocol_table ))), sizeof(dns_protocol_table)/sizeof((dns_protocol_table)[0 ]), ((void)0))), s); }; |