| File: | build-scan/../src/resolve/resolved-dns-answer.c |
| Warning: | line 757, column 24 Potential leak of memory pointed to by 'n' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include "alloc-util.h" | |||
| 4 | #include "dns-domain.h" | |||
| 5 | #include "resolved-dns-answer.h" | |||
| 6 | #include "resolved-dns-dnssec.h" | |||
| 7 | #include "string-util.h" | |||
| 8 | ||||
| 9 | DnsAnswer *dns_answer_new(size_t n) { | |||
| 10 | DnsAnswer *a; | |||
| 11 | ||||
| 12 | a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n)(calloc(1, (__builtin_offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem ) * n))); | |||
| 13 | if (!a) | |||
| 14 | return NULL((void*)0); | |||
| 15 | ||||
| 16 | a->n_ref = 1; | |||
| 17 | a->n_allocated = n; | |||
| 18 | ||||
| 19 | return a; | |||
| 20 | } | |||
| 21 | ||||
| 22 | DnsAnswer *dns_answer_ref(DnsAnswer *a) { | |||
| 23 | if (!a) | |||
| 24 | return NULL((void*)0); | |||
| 25 | ||||
| 26 | assert(a->n_ref > 0)do { if ((__builtin_expect(!!(!(a->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a->n_ref > 0"), "../src/resolve/resolved-dns-answer.c" , 26, __PRETTY_FUNCTION__); } while (0); | |||
| 27 | a->n_ref++; | |||
| 28 | return a; | |||
| 29 | } | |||
| 30 | ||||
| 31 | static void dns_answer_flush(DnsAnswer *a) { | |||
| 32 | DnsResourceRecord *rr; | |||
| 33 | ||||
| 34 | if (!a) | |||
| 35 | return; | |||
| 36 | ||||
| 37 | DNS_ANSWER_FOREACH(rr, a)for (size_t __unique_prefix_i54 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); 0; } ); (a) && (__unique_prefix_i54 < (a)->n_rrs); __unique_prefix_i54 ++, (rr) = (__unique_prefix_i54 < (a)->n_rrs ? (a)-> items[__unique_prefix_i54].rr : ((void*)0))) | |||
| 38 | dns_resource_record_unref(rr); | |||
| 39 | ||||
| 40 | a->n_rrs = 0; | |||
| 41 | } | |||
| 42 | ||||
| 43 | DnsAnswer *dns_answer_unref(DnsAnswer *a) { | |||
| 44 | if (!a) | |||
| 45 | return NULL((void*)0); | |||
| 46 | ||||
| 47 | assert(a->n_ref > 0)do { if ((__builtin_expect(!!(!(a->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a->n_ref > 0"), "../src/resolve/resolved-dns-answer.c" , 47, __PRETTY_FUNCTION__); } while (0); | |||
| 48 | ||||
| 49 | if (a->n_ref == 1) { | |||
| 50 | dns_answer_flush(a); | |||
| 51 | free(a); | |||
| 52 | } else | |||
| 53 | a->n_ref--; | |||
| 54 | ||||
| 55 | return NULL((void*)0); | |||
| 56 | } | |||
| 57 | ||||
| 58 | static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { | |||
| 59 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 59, __PRETTY_FUNCTION__); } while (0); | |||
| 60 | ||||
| 61 | if (!a) | |||
| 62 | return -ENOSPC28; | |||
| 63 | ||||
| 64 | if (a->n_rrs >= a->n_allocated) | |||
| 65 | return -ENOSPC28; | |||
| 66 | ||||
| 67 | a->items[a->n_rrs++] = (DnsAnswerItem) { | |||
| 68 | .rr = dns_resource_record_ref(rr), | |||
| 69 | .ifindex = ifindex, | |||
| 70 | .flags = flags, | |||
| 71 | }; | |||
| 72 | ||||
| 73 | return 1; | |||
| 74 | } | |||
| 75 | ||||
| 76 | static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) { | |||
| 77 | DnsResourceRecord *rr; | |||
| 78 | DnsAnswerFlags flags; | |||
| 79 | int ifindex, r; | |||
| 80 | ||||
| 81 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source)for (size_t __unique_prefix_i55 = ({ (rr) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].rr : ((void *)0); (ifindex) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].ifindex : 0; (flags) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].flags : 0 ; 0; }); (source) && (__unique_prefix_i55 < (source )->n_rrs); __unique_prefix_i55++, (rr) = ((__unique_prefix_i55 < (source)->n_rrs) ? (source)->items[__unique_prefix_i55 ].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i55 < (source )->n_rrs) ? (source)->items[__unique_prefix_i55].ifindex : 0), (flags) = ((__unique_prefix_i55 < (source)->n_rrs ) ? (source)->items[__unique_prefix_i55].flags : 0)) { | |||
| 82 | r = dns_answer_add_raw(a, rr, ifindex, flags); | |||
| 83 | if (r < 0) | |||
| 84 | return r; | |||
| 85 | } | |||
| 86 | ||||
| 87 | return 0; | |||
| 88 | } | |||
| 89 | ||||
| 90 | int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { | |||
| 91 | size_t i; | |||
| 92 | int r; | |||
| 93 | ||||
| 94 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 94, __PRETTY_FUNCTION__); } while (0); | |||
| 95 | ||||
| 96 | if (!a) | |||
| 97 | return -ENOSPC28; | |||
| 98 | if (a->n_ref > 1) | |||
| 99 | return -EBUSY16; | |||
| 100 | ||||
| 101 | for (i = 0; i < a->n_rrs; i++) { | |||
| 102 | if (a->items[i].ifindex != ifindex) | |||
| 103 | continue; | |||
| 104 | ||||
| 105 | r = dns_resource_record_equal(a->items[i].rr, rr); | |||
| 106 | if (r < 0) | |||
| 107 | return r; | |||
| 108 | if (r > 0) { | |||
| 109 | /* Don't mix contradicting TTLs (see below) */ | |||
| 110 | if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0)) | |||
| 111 | return -EINVAL22; | |||
| 112 | ||||
| 113 | /* Entry already exists, keep the entry with | |||
| 114 | * the higher RR. */ | |||
| 115 | if (rr->ttl > a->items[i].rr->ttl) { | |||
| 116 | dns_resource_record_ref(rr); | |||
| 117 | dns_resource_record_unref(a->items[i].rr); | |||
| 118 | a->items[i].rr = rr; | |||
| 119 | } | |||
| 120 | ||||
| 121 | a->items[i].flags |= flags; | |||
| 122 | return 0; | |||
| 123 | } | |||
| 124 | ||||
| 125 | r = dns_resource_key_equal(a->items[i].rr->key, rr->key); | |||
| 126 | if (r < 0) | |||
| 127 | return r; | |||
| 128 | if (r > 0) { | |||
| 129 | /* There's already an RR of the same RRset in | |||
| 130 | * place! Let's see if the TTLs more or less | |||
| 131 | * match. We don't really care if they match | |||
| 132 | * precisely, but we do care whether one is 0 | |||
| 133 | * and the other is not. See RFC 2181, Section | |||
| 134 | * 5.2. */ | |||
| 135 | ||||
| 136 | if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0)) | |||
| 137 | return -EINVAL22; | |||
| 138 | } | |||
| 139 | } | |||
| 140 | ||||
| 141 | return dns_answer_add_raw(a, rr, ifindex, flags); | |||
| 142 | } | |||
| 143 | ||||
| 144 | static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) { | |||
| 145 | DnsResourceRecord *rr; | |||
| 146 | DnsAnswerFlags flags; | |||
| 147 | int ifindex, r; | |||
| 148 | ||||
| 149 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b)for (size_t __unique_prefix_i56 = ({ (rr) = ((b) && ( b)->n_rrs > 0) ? (b)->items[0].rr : ((void*)0); (ifindex ) = ((b) && (b)->n_rrs > 0) ? (b)->items[0]. ifindex : 0; (flags) = ((b) && (b)->n_rrs > 0) ? (b)->items[0].flags : 0; 0; }); (b) && (__unique_prefix_i56 < (b)->n_rrs); __unique_prefix_i56++, (rr) = ((__unique_prefix_i56 < (b)->n_rrs) ? (b)->items[__unique_prefix_i56].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i56 < (b)-> n_rrs) ? (b)->items[__unique_prefix_i56].ifindex : 0), (flags ) = ((__unique_prefix_i56 < (b)->n_rrs) ? (b)->items [__unique_prefix_i56].flags : 0)) { | |||
| 150 | r = dns_answer_add(a, rr, ifindex, flags); | |||
| 151 | if (r < 0) | |||
| 152 | return r; | |||
| 153 | } | |||
| 154 | ||||
| 155 | return 0; | |||
| 156 | } | |||
| 157 | ||||
| 158 | int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { | |||
| 159 | int r; | |||
| 160 | ||||
| 161 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 161, __PRETTY_FUNCTION__); } while (0); | |||
| 162 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 162, __PRETTY_FUNCTION__); } while (0); | |||
| 163 | ||||
| 164 | r = dns_answer_reserve_or_clone(a, 1); | |||
| 165 | if (r < 0) | |||
| 166 | return r; | |||
| 167 | ||||
| 168 | return dns_answer_add(*a, rr, ifindex, flags); | |||
| 169 | } | |||
| 170 | ||||
| 171 | int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) { | |||
| 172 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *soa = NULL((void*)0); | |||
| 173 | ||||
| 174 | soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name); | |||
| 175 | if (!soa) | |||
| 176 | return -ENOMEM12; | |||
| 177 | ||||
| 178 | soa->ttl = ttl; | |||
| 179 | ||||
| 180 | soa->soa.mname = strdup(name); | |||
| 181 | if (!soa->soa.mname) | |||
| 182 | return -ENOMEM12; | |||
| 183 | ||||
| 184 | soa->soa.rname = strappend("root.", name); | |||
| 185 | if (!soa->soa.rname) | |||
| 186 | return -ENOMEM12; | |||
| 187 | ||||
| 188 | soa->soa.serial = 1; | |||
| 189 | soa->soa.refresh = 1; | |||
| 190 | soa->soa.retry = 1; | |||
| 191 | soa->soa.expire = 1; | |||
| 192 | soa->soa.minimum = ttl; | |||
| 193 | ||||
| 194 | return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED); | |||
| 195 | } | |||
| 196 | ||||
| 197 | int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { | |||
| 198 | DnsAnswerFlags flags = 0, i_flags; | |||
| 199 | DnsResourceRecord *i; | |||
| 200 | bool_Bool found = false0; | |||
| 201 | int r; | |||
| 202 | ||||
| 203 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 203, __PRETTY_FUNCTION__); } while (0); | |||
| 204 | ||||
| 205 | DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a)for (size_t __unique_prefix_i57 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (i_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i57 < (a )->n_rrs); __unique_prefix_i57++, (i) = ((__unique_prefix_i57 < (a)->n_rrs) ? (a)->items[__unique_prefix_i57].rr : ((void*)0)), (i_flags) = ((__unique_prefix_i57 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i57].flags : 0)) { | |||
| 206 | r = dns_resource_key_match_rr(key, i, NULL((void*)0)); | |||
| 207 | if (r < 0) | |||
| 208 | return r; | |||
| 209 | if (r == 0) | |||
| 210 | continue; | |||
| 211 | ||||
| 212 | if (!ret_flags) | |||
| 213 | return 1; | |||
| 214 | ||||
| 215 | if (found) | |||
| 216 | flags &= i_flags; | |||
| 217 | else { | |||
| 218 | flags = i_flags; | |||
| 219 | found = true1; | |||
| 220 | } | |||
| 221 | } | |||
| 222 | ||||
| 223 | if (ret_flags) | |||
| 224 | *ret_flags = flags; | |||
| 225 | ||||
| 226 | return found; | |||
| 227 | } | |||
| 228 | ||||
| 229 | int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *ret_flags) { | |||
| 230 | DnsAnswerFlags flags = 0, i_flags; | |||
| 231 | DnsResourceRecord *i; | |||
| 232 | bool_Bool found = false0; | |||
| 233 | int r; | |||
| 234 | ||||
| 235 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 235, __PRETTY_FUNCTION__); } while (0); | |||
| 236 | ||||
| 237 | DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a)for (size_t __unique_prefix_i58 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (i_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i58 < (a )->n_rrs); __unique_prefix_i58++, (i) = ((__unique_prefix_i58 < (a)->n_rrs) ? (a)->items[__unique_prefix_i58].rr : ((void*)0)), (i_flags) = ((__unique_prefix_i58 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i58].flags : 0)) { | |||
| 238 | r = dns_resource_record_equal(i, rr); | |||
| 239 | if (r < 0) | |||
| 240 | return r; | |||
| 241 | if (r == 0) | |||
| 242 | continue; | |||
| 243 | ||||
| 244 | if (!ret_flags) | |||
| 245 | return 1; | |||
| 246 | ||||
| 247 | if (found) | |||
| 248 | flags &= i_flags; | |||
| 249 | else { | |||
| 250 | flags = i_flags; | |||
| 251 | found = true1; | |||
| 252 | } | |||
| 253 | } | |||
| 254 | ||||
| 255 | if (ret_flags) | |||
| 256 | *ret_flags = flags; | |||
| 257 | ||||
| 258 | return found; | |||
| 259 | } | |||
| 260 | ||||
| 261 | int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { | |||
| 262 | DnsAnswerFlags flags = 0, i_flags; | |||
| 263 | DnsResourceRecord *i; | |||
| 264 | bool_Bool found = false0; | |||
| 265 | int r; | |||
| 266 | ||||
| 267 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 267, __PRETTY_FUNCTION__); } while (0); | |||
| 268 | ||||
| 269 | DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a)for (size_t __unique_prefix_i59 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (i_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i59 < (a )->n_rrs); __unique_prefix_i59++, (i) = ((__unique_prefix_i59 < (a)->n_rrs) ? (a)->items[__unique_prefix_i59].rr : ((void*)0)), (i_flags) = ((__unique_prefix_i59 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i59].flags : 0)) { | |||
| 270 | r = dns_resource_key_equal(i->key, key); | |||
| 271 | if (r < 0) | |||
| 272 | return r; | |||
| 273 | if (r == 0) | |||
| 274 | continue; | |||
| 275 | ||||
| 276 | if (!ret_flags) | |||
| 277 | return true1; | |||
| 278 | ||||
| 279 | if (found) | |||
| 280 | flags &= i_flags; | |||
| 281 | else { | |||
| 282 | flags = i_flags; | |||
| 283 | found = true1; | |||
| 284 | } | |||
| 285 | } | |||
| 286 | ||||
| 287 | if (ret_flags) | |||
| 288 | *ret_flags = flags; | |||
| 289 | ||||
| 290 | return found; | |||
| 291 | } | |||
| 292 | ||||
| 293 | int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) { | |||
| 294 | DnsResourceRecord *i; | |||
| 295 | ||||
| 296 | DNS_ANSWER_FOREACH(i, a)for (size_t __unique_prefix_i60 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); 0; }) ; (a) && (__unique_prefix_i60 < (a)->n_rrs); __unique_prefix_i60 ++, (i) = (__unique_prefix_i60 < (a)->n_rrs ? (a)->items [__unique_prefix_i60].rr : ((void*)0))) { | |||
| 297 | if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_TYPE_NSEC, DNS_TYPE_NSEC3})/sizeof(int )]; switch(i->key->type) { case DNS_TYPE_NSEC: case DNS_TYPE_NSEC3 : _found = 1; break; default: break; } _found; })) | |||
| 298 | return true1; | |||
| 299 | } | |||
| 300 | ||||
| 301 | return false0; | |||
| 302 | } | |||
| 303 | ||||
| 304 | int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) { | |||
| 305 | DnsResourceRecord *rr; | |||
| 306 | int r; | |||
| 307 | ||||
| 308 | /* Checks whether the specified answer contains at least one NSEC3 RR in the specified zone */ | |||
| 309 | ||||
| 310 | DNS_ANSWER_FOREACH(rr, answer)for (size_t __unique_prefix_i61 = ({ (rr) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].rr : ((void *)0); 0; }); (answer) && (__unique_prefix_i61 < (answer )->n_rrs); __unique_prefix_i61++, (rr) = (__unique_prefix_i61 < (answer)->n_rrs ? (answer)->items[__unique_prefix_i61 ].rr : ((void*)0))) { | |||
| 311 | const char *p; | |||
| 312 | ||||
| 313 | if (rr->key->type != DNS_TYPE_NSEC3) | |||
| 314 | continue; | |||
| 315 | ||||
| 316 | p = dns_resource_key_name(rr->key); | |||
| 317 | r = dns_name_parent(&p); | |||
| 318 | if (r < 0) | |||
| 319 | return r; | |||
| 320 | if (r == 0) | |||
| 321 | continue; | |||
| 322 | ||||
| 323 | r = dns_name_equal(p, zone); | |||
| 324 | if (r != 0) | |||
| 325 | return r; | |||
| 326 | } | |||
| 327 | ||||
| 328 | return false0; | |||
| 329 | } | |||
| 330 | ||||
| 331 | int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { | |||
| 332 | DnsResourceRecord *rr, *soa = NULL((void*)0); | |||
| 333 | DnsAnswerFlags rr_flags, soa_flags = 0; | |||
| 334 | int r; | |||
| 335 | ||||
| 336 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 336, __PRETTY_FUNCTION__); } while (0); | |||
| 337 | ||||
| 338 | /* For a SOA record we can never find a matching SOA record */ | |||
| 339 | if (key->type == DNS_TYPE_SOA) | |||
| 340 | return 0; | |||
| 341 | ||||
| 342 | DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a)for (size_t __unique_prefix_i62 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (rr_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i62 < (a )->n_rrs); __unique_prefix_i62++, (rr) = ((__unique_prefix_i62 < (a)->n_rrs) ? (a)->items[__unique_prefix_i62].rr : ((void*)0)), (rr_flags) = ((__unique_prefix_i62 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i62].flags : 0)) { | |||
| 343 | r = dns_resource_key_match_soa(key, rr->key); | |||
| 344 | if (r < 0) | |||
| 345 | return r; | |||
| 346 | if (r > 0) { | |||
| 347 | ||||
| 348 | if (soa) { | |||
| 349 | r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(soa->key)); | |||
| 350 | if (r < 0) | |||
| 351 | return r; | |||
| 352 | if (r > 0) | |||
| 353 | continue; | |||
| 354 | } | |||
| 355 | ||||
| 356 | soa = rr; | |||
| 357 | soa_flags = rr_flags; | |||
| 358 | } | |||
| 359 | } | |||
| 360 | ||||
| 361 | if (!soa) | |||
| 362 | return 0; | |||
| 363 | ||||
| 364 | if (ret) | |||
| 365 | *ret = soa; | |||
| 366 | if (flags) | |||
| 367 | *flags = soa_flags; | |||
| 368 | ||||
| 369 | return 1; | |||
| 370 | } | |||
| 371 | ||||
| 372 | int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { | |||
| 373 | DnsResourceRecord *rr; | |||
| 374 | DnsAnswerFlags rr_flags; | |||
| 375 | int r; | |||
| 376 | ||||
| 377 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 377, __PRETTY_FUNCTION__); } while (0); | |||
| 378 | ||||
| 379 | /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */ | |||
| 380 | if (!dns_type_may_redirect(key->type)) | |||
| 381 | return 0; | |||
| 382 | ||||
| 383 | DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a)for (size_t __unique_prefix_i63 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (rr_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i63 < (a )->n_rrs); __unique_prefix_i63++, (rr) = ((__unique_prefix_i63 < (a)->n_rrs) ? (a)->items[__unique_prefix_i63].rr : ((void*)0)), (rr_flags) = ((__unique_prefix_i63 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i63].flags : 0)) { | |||
| 384 | r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL((void*)0)); | |||
| 385 | if (r < 0) | |||
| 386 | return r; | |||
| 387 | if (r > 0) { | |||
| 388 | if (ret) | |||
| 389 | *ret = rr; | |||
| 390 | if (flags) | |||
| 391 | *flags = rr_flags; | |||
| 392 | return 1; | |||
| 393 | } | |||
| 394 | } | |||
| 395 | ||||
| 396 | return 0; | |||
| 397 | } | |||
| 398 | ||||
| 399 | int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) { | |||
| 400 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *k = NULL((void*)0); | |||
| 401 | int r; | |||
| 402 | ||||
| 403 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-answer.c" , 403, __PRETTY_FUNCTION__); } while (0); | |||
| 404 | ||||
| 405 | if (dns_answer_size(a) <= 0) { | |||
| 406 | *ret = dns_answer_ref(b); | |||
| 407 | return 0; | |||
| 408 | } | |||
| 409 | ||||
| 410 | if (dns_answer_size(b) <= 0) { | |||
| 411 | *ret = dns_answer_ref(a); | |||
| 412 | return 0; | |||
| 413 | } | |||
| 414 | ||||
| 415 | k = dns_answer_new(a->n_rrs + b->n_rrs); | |||
| 416 | if (!k) | |||
| 417 | return -ENOMEM12; | |||
| 418 | ||||
| 419 | r = dns_answer_add_raw_all(k, a); | |||
| 420 | if (r < 0) | |||
| 421 | return r; | |||
| 422 | ||||
| 423 | r = dns_answer_add_all(k, b); | |||
| 424 | if (r < 0) | |||
| 425 | return r; | |||
| 426 | ||||
| 427 | *ret = TAKE_PTR(k)({ typeof(k) _ptr_ = (k); (k) = ((void*)0); _ptr_; }); | |||
| 428 | ||||
| 429 | return 0; | |||
| 430 | } | |||
| 431 | ||||
| 432 | int dns_answer_extend(DnsAnswer **a, DnsAnswer *b) { | |||
| 433 | DnsAnswer *merged; | |||
| 434 | int r; | |||
| 435 | ||||
| 436 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 436, __PRETTY_FUNCTION__); } while (0); | |||
| 437 | ||||
| 438 | r = dns_answer_merge(*a, b, &merged); | |||
| 439 | if (r < 0) | |||
| 440 | return r; | |||
| 441 | ||||
| 442 | dns_answer_unref(*a); | |||
| 443 | *a = merged; | |||
| 444 | ||||
| 445 | return 0; | |||
| 446 | } | |||
| 447 | ||||
| 448 | int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) { | |||
| 449 | bool_Bool found = false0, other = false0; | |||
| 450 | DnsResourceRecord *rr; | |||
| 451 | size_t i; | |||
| 452 | int r; | |||
| 453 | ||||
| 454 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 454, __PRETTY_FUNCTION__); } while (0); | |||
| 455 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 455, __PRETTY_FUNCTION__); } while (0); | |||
| 456 | ||||
| 457 | /* Remove all entries matching the specified key from *a */ | |||
| 458 | ||||
| 459 | DNS_ANSWER_FOREACH(rr, *a)for (size_t __unique_prefix_i64 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); 0; }); (*a) && (__unique_prefix_i64 < (*a)->n_rrs ); __unique_prefix_i64++, (rr) = (__unique_prefix_i64 < (* a)->n_rrs ? (*a)->items[__unique_prefix_i64].rr : ((void *)0))) { | |||
| 460 | r = dns_resource_key_equal(rr->key, key); | |||
| 461 | if (r < 0) | |||
| 462 | return r; | |||
| 463 | if (r > 0) | |||
| 464 | found = true1; | |||
| 465 | else | |||
| 466 | other = true1; | |||
| 467 | ||||
| 468 | if (found && other) | |||
| 469 | break; | |||
| 470 | } | |||
| 471 | ||||
| 472 | if (!found) | |||
| 473 | return 0; | |||
| 474 | ||||
| 475 | if (!other) { | |||
| 476 | *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ | |||
| 477 | return 1; | |||
| 478 | } | |||
| 479 | ||||
| 480 | if ((*a)->n_ref > 1) { | |||
| 481 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *copy = NULL((void*)0); | |||
| 482 | DnsAnswerFlags flags; | |||
| 483 | int ifindex; | |||
| 484 | ||||
| 485 | copy = dns_answer_new((*a)->n_rrs); | |||
| 486 | if (!copy) | |||
| 487 | return -ENOMEM12; | |||
| 488 | ||||
| 489 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a)for (size_t __unique_prefix_i65 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); (ifindex ) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[ 0].ifindex : 0; (flags) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[0].flags : 0; 0; }); (*a) && (__unique_prefix_i65 < (*a)->n_rrs); __unique_prefix_i65++, (rr) = ((__unique_prefix_i65 < (*a)->n_rrs) ? (*a)->items[__unique_prefix_i65].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i65 < (*a)-> n_rrs) ? (*a)->items[__unique_prefix_i65].ifindex : 0), (flags ) = ((__unique_prefix_i65 < (*a)->n_rrs) ? (*a)->items [__unique_prefix_i65].flags : 0)) { | |||
| 490 | r = dns_resource_key_equal(rr->key, key); | |||
| 491 | if (r < 0) | |||
| 492 | return r; | |||
| 493 | if (r > 0) | |||
| 494 | continue; | |||
| 495 | ||||
| 496 | r = dns_answer_add_raw(copy, rr, ifindex, flags); | |||
| 497 | if (r < 0) | |||
| 498 | return r; | |||
| 499 | } | |||
| 500 | ||||
| 501 | dns_answer_unref(*a); | |||
| 502 | *a = TAKE_PTR(copy)({ typeof(copy) _ptr_ = (copy); (copy) = ((void*)0); _ptr_; } ); | |||
| 503 | ||||
| 504 | return 1; | |||
| 505 | } | |||
| 506 | ||||
| 507 | /* Only a single reference, edit in-place */ | |||
| 508 | ||||
| 509 | i = 0; | |||
| 510 | for (;;) { | |||
| 511 | if (i >= (*a)->n_rrs) | |||
| 512 | break; | |||
| 513 | ||||
| 514 | r = dns_resource_key_equal((*a)->items[i].rr->key, key); | |||
| 515 | if (r < 0) | |||
| 516 | return r; | |||
| 517 | if (r > 0) { | |||
| 518 | /* Kill this entry */ | |||
| 519 | ||||
| 520 | dns_resource_record_unref((*a)->items[i].rr); | |||
| 521 | memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); | |||
| 522 | (*a)->n_rrs--; | |||
| 523 | continue; | |||
| 524 | ||||
| 525 | } else | |||
| 526 | /* Keep this entry */ | |||
| 527 | i++; | |||
| 528 | } | |||
| 529 | ||||
| 530 | return 1; | |||
| 531 | } | |||
| 532 | ||||
| 533 | int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) { | |||
| 534 | bool_Bool found = false0, other = false0; | |||
| 535 | DnsResourceRecord *rr; | |||
| 536 | size_t i; | |||
| 537 | int r; | |||
| 538 | ||||
| 539 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 539, __PRETTY_FUNCTION__); } while (0); | |||
| 540 | assert(rm)do { if ((__builtin_expect(!!(!(rm)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rm"), "../src/resolve/resolved-dns-answer.c" , 540, __PRETTY_FUNCTION__); } while (0); | |||
| 541 | ||||
| 542 | /* Remove all entries matching the specified RR from *a */ | |||
| 543 | ||||
| 544 | DNS_ANSWER_FOREACH(rr, *a)for (size_t __unique_prefix_i66 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); 0; }); (*a) && (__unique_prefix_i66 < (*a)->n_rrs ); __unique_prefix_i66++, (rr) = (__unique_prefix_i66 < (* a)->n_rrs ? (*a)->items[__unique_prefix_i66].rr : ((void *)0))) { | |||
| 545 | r = dns_resource_record_equal(rr, rm); | |||
| 546 | if (r < 0) | |||
| 547 | return r; | |||
| 548 | if (r > 0) | |||
| 549 | found = true1; | |||
| 550 | else | |||
| 551 | other = true1; | |||
| 552 | ||||
| 553 | if (found && other) | |||
| 554 | break; | |||
| 555 | } | |||
| 556 | ||||
| 557 | if (!found) | |||
| 558 | return 0; | |||
| 559 | ||||
| 560 | if (!other) { | |||
| 561 | *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ | |||
| 562 | return 1; | |||
| 563 | } | |||
| 564 | ||||
| 565 | if ((*a)->n_ref > 1) { | |||
| 566 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *copy = NULL((void*)0); | |||
| 567 | DnsAnswerFlags flags; | |||
| 568 | int ifindex; | |||
| 569 | ||||
| 570 | copy = dns_answer_new((*a)->n_rrs); | |||
| 571 | if (!copy) | |||
| 572 | return -ENOMEM12; | |||
| 573 | ||||
| 574 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a)for (size_t __unique_prefix_i67 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); (ifindex ) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[ 0].ifindex : 0; (flags) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[0].flags : 0; 0; }); (*a) && (__unique_prefix_i67 < (*a)->n_rrs); __unique_prefix_i67++, (rr) = ((__unique_prefix_i67 < (*a)->n_rrs) ? (*a)->items[__unique_prefix_i67].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i67 < (*a)-> n_rrs) ? (*a)->items[__unique_prefix_i67].ifindex : 0), (flags ) = ((__unique_prefix_i67 < (*a)->n_rrs) ? (*a)->items [__unique_prefix_i67].flags : 0)) { | |||
| 575 | r = dns_resource_record_equal(rr, rm); | |||
| 576 | if (r < 0) | |||
| 577 | return r; | |||
| 578 | if (r > 0) | |||
| 579 | continue; | |||
| 580 | ||||
| 581 | r = dns_answer_add_raw(copy, rr, ifindex, flags); | |||
| 582 | if (r < 0) | |||
| 583 | return r; | |||
| 584 | } | |||
| 585 | ||||
| 586 | dns_answer_unref(*a); | |||
| 587 | *a = TAKE_PTR(copy)({ typeof(copy) _ptr_ = (copy); (copy) = ((void*)0); _ptr_; } ); | |||
| 588 | ||||
| 589 | return 1; | |||
| 590 | } | |||
| 591 | ||||
| 592 | /* Only a single reference, edit in-place */ | |||
| 593 | ||||
| 594 | i = 0; | |||
| 595 | for (;;) { | |||
| 596 | if (i >= (*a)->n_rrs) | |||
| 597 | break; | |||
| 598 | ||||
| 599 | r = dns_resource_record_equal((*a)->items[i].rr, rm); | |||
| 600 | if (r < 0) | |||
| 601 | return r; | |||
| 602 | if (r > 0) { | |||
| 603 | /* Kill this entry */ | |||
| 604 | ||||
| 605 | dns_resource_record_unref((*a)->items[i].rr); | |||
| 606 | memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); | |||
| 607 | (*a)->n_rrs--; | |||
| 608 | continue; | |||
| 609 | ||||
| 610 | } else | |||
| 611 | /* Keep this entry */ | |||
| 612 | i++; | |||
| 613 | } | |||
| 614 | ||||
| 615 | return 1; | |||
| 616 | } | |||
| 617 | ||||
| 618 | int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) { | |||
| 619 | DnsResourceRecord *rr_source; | |||
| 620 | int ifindex_source, r; | |||
| 621 | DnsAnswerFlags flags_source; | |||
| 622 | ||||
| 623 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 623, __PRETTY_FUNCTION__); } while (0); | |||
| 624 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 624, __PRETTY_FUNCTION__); } while (0); | |||
| 625 | ||||
| 626 | /* Copy all RRs matching the specified key from source into *a */ | |||
| 627 | ||||
| 628 | DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source)for (size_t __unique_prefix_i68 = ({ (rr_source) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].rr : ((void *)0); (ifindex_source) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].ifindex : 0; (flags_source) = ((source) && (source)->n_rrs > 0) ? (source)-> items[0].flags : 0; 0; }); (source) && (__unique_prefix_i68 < (source)->n_rrs); __unique_prefix_i68++, (rr_source) = ((__unique_prefix_i68 < (source)->n_rrs) ? (source)-> items[__unique_prefix_i68].rr : ((void*)0)), (ifindex_source) = ((__unique_prefix_i68 < (source)->n_rrs) ? (source)-> items[__unique_prefix_i68].ifindex : 0), (flags_source) = ((__unique_prefix_i68 < (source)->n_rrs) ? (source)->items[__unique_prefix_i68 ].flags : 0)) { | |||
| 629 | ||||
| 630 | r = dns_resource_key_equal(rr_source->key, key); | |||
| 631 | if (r < 0) | |||
| 632 | return r; | |||
| 633 | if (r == 0) | |||
| 634 | continue; | |||
| 635 | ||||
| 636 | /* Make space for at least one entry */ | |||
| 637 | r = dns_answer_reserve_or_clone(a, 1); | |||
| 638 | if (r < 0) | |||
| 639 | return r; | |||
| 640 | ||||
| 641 | r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags); | |||
| 642 | if (r < 0) | |||
| 643 | return r; | |||
| 644 | } | |||
| 645 | ||||
| 646 | return 0; | |||
| 647 | } | |||
| 648 | ||||
| 649 | int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) { | |||
| 650 | int r; | |||
| 651 | ||||
| 652 | assert(to)do { if ((__builtin_expect(!!(!(to)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("to"), "../src/resolve/resolved-dns-answer.c" , 652, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 653 | assert(from)do { if ((__builtin_expect(!!(!(from)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("from"), "../src/resolve/resolved-dns-answer.c" , 653, __PRETTY_FUNCTION__); } while (0); | |||
| 654 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 654, __PRETTY_FUNCTION__); } while (0); | |||
| 655 | ||||
| 656 | r = dns_answer_copy_by_key(to, *from, key, or_flags); | |||
| 657 | if (r < 0) | |||
| 658 | return r; | |||
| 659 | ||||
| 660 | return dns_answer_remove_by_key(from, key); | |||
| 661 | } | |||
| 662 | ||||
| 663 | void dns_answer_order_by_scope(DnsAnswer *a, bool_Bool prefer_link_local) { | |||
| 664 | DnsAnswerItem *items; | |||
| 665 | size_t i, start, end; | |||
| 666 | ||||
| 667 | if (!a) | |||
| 668 | return; | |||
| 669 | ||||
| 670 | if (a->n_rrs <= 1) | |||
| 671 | return; | |||
| 672 | ||||
| 673 | start = 0; | |||
| 674 | end = a->n_rrs-1; | |||
| 675 | ||||
| 676 | /* RFC 4795, Section 2.6 suggests we should order entries | |||
| 677 | * depending on whether the sender is a link-local address. */ | |||
| 678 | ||||
| 679 | items = newa(DnsAnswerItem, a->n_rrs)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (DnsAnswerItem), a->n_rrs))),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(DnsAnswerItem), a->n_rrs)" ), "../src/resolve/resolved-dns-answer.c", 679, __PRETTY_FUNCTION__ ); } while (0); (DnsAnswerItem*) __builtin_alloca (sizeof(DnsAnswerItem )*(a->n_rrs)); }); | |||
| 680 | for (i = 0; i < a->n_rrs; i++) { | |||
| 681 | ||||
| 682 | if (a->items[i].rr->key->class == DNS_CLASS_IN && | |||
| 683 | ((a->items[i].rr->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET2, (union in_addr_union*) &a->items[i].rr->a.in_addr) != prefer_link_local) || | |||
| 684 | (a->items[i].rr->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET610, (union in_addr_union*) &a->items[i].rr->aaaa.in6_addr) != prefer_link_local))) | |||
| 685 | /* Order address records that are not preferred to the end of the array */ | |||
| 686 | items[end--] = a->items[i]; | |||
| 687 | else | |||
| 688 | /* Order all other records to the beginning of the array */ | |||
| 689 | items[start++] = a->items[i]; | |||
| 690 | } | |||
| 691 | ||||
| 692 | assert(start == end+1)do { if ((__builtin_expect(!!(!(start == end+1)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("start == end+1"), "../src/resolve/resolved-dns-answer.c" , 692, __PRETTY_FUNCTION__); } while (0); | |||
| 693 | memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs); | |||
| 694 | } | |||
| 695 | ||||
| 696 | int dns_answer_reserve(DnsAnswer **a, size_t n_free) { | |||
| 697 | DnsAnswer *n; | |||
| 698 | ||||
| 699 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 699, __PRETTY_FUNCTION__); } while (0); | |||
| 700 | ||||
| 701 | if (n_free <= 0) | |||
| 702 | return 0; | |||
| 703 | ||||
| 704 | if (*a) { | |||
| 705 | size_t ns; | |||
| 706 | ||||
| 707 | if ((*a)->n_ref > 1) | |||
| 708 | return -EBUSY16; | |||
| 709 | ||||
| 710 | ns = (*a)->n_rrs + n_free; | |||
| 711 | ||||
| 712 | if ((*a)->n_allocated >= ns) | |||
| 713 | return 0; | |||
| 714 | ||||
| 715 | /* Allocate more than we need */ | |||
| 716 | ns *= 2; | |||
| 717 | ||||
| 718 | n = realloc(*a, offsetof(DnsAnswer, items)__builtin_offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns); | |||
| 719 | if (!n) | |||
| 720 | return -ENOMEM12; | |||
| 721 | ||||
| 722 | n->n_allocated = ns; | |||
| 723 | } else { | |||
| 724 | n = dns_answer_new(n_free); | |||
| 725 | if (!n) | |||
| 726 | return -ENOMEM12; | |||
| 727 | } | |||
| 728 | ||||
| 729 | *a = n; | |||
| 730 | return 0; | |||
| 731 | } | |||
| 732 | ||||
| 733 | int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) { | |||
| 734 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *n = NULL((void*)0); | |||
| 735 | int r; | |||
| 736 | ||||
| 737 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 737, __PRETTY_FUNCTION__); } while (0); | |||
| 738 | ||||
| 739 | /* Tries to extend the DnsAnswer object. And if that's not | |||
| 740 | * possible, since we are not the sole owner, then allocate a | |||
| 741 | * new, appropriately sized one. Either way, after this call | |||
| 742 | * the object will only have a single reference, and has room | |||
| 743 | * for at least the specified number of RRs. */ | |||
| 744 | ||||
| 745 | r = dns_answer_reserve(a, n_free); | |||
| 746 | if (r != -EBUSY16) | |||
| 747 | return r; | |||
| 748 | ||||
| 749 | assert(*a)do { if ((__builtin_expect(!!(!(*a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*a"), "../src/resolve/resolved-dns-answer.c" , 749, __PRETTY_FUNCTION__); } while (0); | |||
| 750 | ||||
| 751 | n = dns_answer_new(((*a)->n_rrs + n_free) * 2); | |||
| 752 | if (!n
| |||
| 753 | return -ENOMEM12; | |||
| 754 | ||||
| 755 | r = dns_answer_add_raw_all(n, *a); | |||
| 756 | if (r
| |||
| 757 | return r; | |||
| ||||
| 758 | ||||
| 759 | dns_answer_unref(*a); | |||
| 760 | *a = TAKE_PTR(n)({ typeof(n) _ptr_ = (n); (n) = ((void*)0); _ptr_; }); | |||
| 761 | ||||
| 762 | return 0; | |||
| 763 | } | |||
| 764 | ||||
| 765 | void dns_answer_dump(DnsAnswer *answer, FILE *f) { | |||
| 766 | DnsResourceRecord *rr; | |||
| 767 | DnsAnswerFlags flags; | |||
| 768 | int ifindex; | |||
| 769 | ||||
| 770 | if (!f) | |||
| 771 | f = stdoutstdout; | |||
| 772 | ||||
| 773 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer)for (size_t __unique_prefix_i69 = ({ (rr) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].rr : ((void *)0); (ifindex) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].ifindex : 0; (flags) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].flags : 0 ; 0; }); (answer) && (__unique_prefix_i69 < (answer )->n_rrs); __unique_prefix_i69++, (rr) = ((__unique_prefix_i69 < (answer)->n_rrs) ? (answer)->items[__unique_prefix_i69 ].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i69 < (answer )->n_rrs) ? (answer)->items[__unique_prefix_i69].ifindex : 0), (flags) = ((__unique_prefix_i69 < (answer)->n_rrs ) ? (answer)->items[__unique_prefix_i69].flags : 0)) { | |||
| 774 | const char *t; | |||
| 775 | ||||
| 776 | fputc('\t', f); | |||
| 777 | ||||
| 778 | t = dns_resource_record_to_string(rr); | |||
| 779 | if (!t) { | |||
| 780 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-dns-answer.c" , 780, __func__); | |||
| 781 | continue; | |||
| 782 | } | |||
| 783 | ||||
| 784 | fputs(t, f); | |||
| 785 | ||||
| 786 | if (ifindex != 0 || flags & (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE|DNS_ANSWER_SHARED_OWNER)) | |||
| 787 | fputs("\t;", f); | |||
| 788 | ||||
| 789 | if (ifindex != 0) | |||
| 790 | printf(" ifindex=%i", ifindex); | |||
| 791 | if (flags & DNS_ANSWER_AUTHENTICATED) | |||
| 792 | fputs(" authenticated", f); | |||
| 793 | if (flags & DNS_ANSWER_CACHEABLE) | |||
| 794 | fputs(" cachable", f); | |||
| 795 | if (flags & DNS_ANSWER_SHARED_OWNER) | |||
| 796 | fputs(" shared-owner", f); | |||
| 797 | ||||
| 798 | fputc('\n', f); | |||
| 799 | } | |||
| 800 | } | |||
| 801 | ||||
| 802 | bool_Bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) { | |||
| 803 | DnsResourceRecord *rr; | |||
| 804 | int r; | |||
| 805 | ||||
| 806 | assert(cname)do { if ((__builtin_expect(!!(!(cname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("cname"), "../src/resolve/resolved-dns-answer.c" , 806, __PRETTY_FUNCTION__); } while (0); | |||
| 807 | ||||
| 808 | /* Checks whether the answer contains a DNAME record that indicates that the specified CNAME record is | |||
| 809 | * synthesized from it */ | |||
| 810 | ||||
| 811 | if (cname->key->type != DNS_TYPE_CNAME) | |||
| 812 | return 0; | |||
| 813 | ||||
| 814 | DNS_ANSWER_FOREACH(rr, a)for (size_t __unique_prefix_i70 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); 0; } ); (a) && (__unique_prefix_i70 < (a)->n_rrs); __unique_prefix_i70 ++, (rr) = (__unique_prefix_i70 < (a)->n_rrs ? (a)-> items[__unique_prefix_i70].rr : ((void*)0))) { | |||
| 815 | _cleanup_free___attribute__((cleanup(freep))) char *n = NULL((void*)0); | |||
| 816 | ||||
| 817 | if (rr->key->type != DNS_TYPE_DNAME) | |||
| 818 | continue; | |||
| 819 | if (rr->key->class != cname->key->class) | |||
| 820 | continue; | |||
| 821 | ||||
| 822 | r = dns_name_change_suffix(cname->cname.name, rr->dname.name, dns_resource_key_name(rr->key), &n); | |||
| 823 | if (r < 0) | |||
| 824 | return r; | |||
| 825 | if (r == 0) | |||
| 826 | continue; | |||
| 827 | ||||
| 828 | r = dns_name_equal(n, dns_resource_key_name(cname->key)); | |||
| 829 | if (r < 0) | |||
| 830 | return r; | |||
| 831 | if (r > 0) | |||
| 832 | return 1; | |||
| 833 | ||||
| 834 | } | |||
| 835 | ||||
| 836 | return 0; | |||
| 837 | } |