]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-question.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "alloc-util.h"
23 #include "dns-domain.h"
24 #include "resolved-dns-question.h"
26 DnsQuestion
*dns_question_new(unsigned n
) {
31 q
= malloc0(offsetof(DnsQuestion
, keys
) + sizeof(DnsResourceKey
*) * n
);
41 DnsQuestion
*dns_question_ref(DnsQuestion
*q
) {
50 DnsQuestion
*dns_question_unref(DnsQuestion
*q
) {
59 for (i
= 0; i
< q
->n_keys
; i
++)
60 dns_resource_key_unref(q
->keys
[i
]);
68 int dns_question_add(DnsQuestion
*q
, DnsResourceKey
*key
) {
77 for (i
= 0; i
< q
->n_keys
; i
++) {
78 r
= dns_resource_key_equal(q
->keys
[i
], key
);
85 if (q
->n_keys
>= q
->n_allocated
)
88 q
->keys
[q
->n_keys
++] = dns_resource_key_ref(key
);
92 int dns_question_matches_rr(DnsQuestion
*q
, DnsResourceRecord
*rr
, const char *search_domain
) {
101 for (i
= 0; i
< q
->n_keys
; i
++) {
102 r
= dns_resource_key_match_rr(q
->keys
[i
], rr
, search_domain
);
110 int dns_question_matches_cname(DnsQuestion
*q
, DnsResourceRecord
*rr
, const char *search_domain
) {
119 for (i
= 0; i
< q
->n_keys
; i
++) {
120 r
= dns_resource_key_match_cname_or_dname(q
->keys
[i
], rr
->key
, search_domain
);
128 int dns_question_is_valid_for_query(DnsQuestion
*q
) {
139 if (q
->n_keys
> 65535)
142 name
= DNS_RESOURCE_KEY_NAME(q
->keys
[0]);
146 /* Check that all keys in this question bear the same name */
147 for (i
= 1; i
< q
->n_keys
; i
++) {
150 r
= dns_name_equal(DNS_RESOURCE_KEY_NAME(q
->keys
[i
]), name
);
158 int dns_question_contains(DnsQuestion
*a
, DnsResourceKey
*k
) {
167 for (j
= 0; j
< a
->n_keys
; j
++) {
168 r
= dns_resource_key_equal(a
->keys
[j
], k
);
176 int dns_question_is_equal(DnsQuestion
*a
, DnsQuestion
*b
) {
181 return !b
|| b
->n_keys
== 0;
183 return a
->n_keys
== 0;
185 /* Checks if all keys in a are also contained b, and vice versa */
187 for (j
= 0; j
< a
->n_keys
; j
++) {
188 r
= dns_question_contains(b
, a
->keys
[j
]);
193 for (j
= 0; j
< b
->n_keys
; j
++) {
194 r
= dns_question_contains(a
, b
->keys
[j
]);
202 int dns_question_cname_redirect(DnsQuestion
*q
, const DnsResourceRecord
*cname
, DnsQuestion
**ret
) {
203 _cleanup_(dns_question_unrefp
) DnsQuestion
*n
= NULL
;
210 assert(IN_SET(cname
->key
->type
, DNS_TYPE_CNAME
, DNS_TYPE_DNAME
));
213 n
= dns_question_new(0);
222 for (i
= 0; i
< q
->n_keys
; i
++) {
223 _cleanup_free_
char *destination
= NULL
;
226 if (cname
->key
->type
== DNS_TYPE_CNAME
)
227 d
= cname
->cname
.name
;
229 r
= dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(q
->keys
[i
]), DNS_RESOURCE_KEY_NAME(cname
->key
), cname
->dname
.name
, &destination
);
238 r
= dns_name_equal(DNS_RESOURCE_KEY_NAME(q
->keys
[i
]), d
);
249 /* Shortcut, the names are already right */
250 *ret
= dns_question_ref(q
);
254 n
= dns_question_new(q
->n_keys
);
258 /* Create a new question, and patch in the new name */
259 for (i
= 0; i
< q
->n_keys
; i
++) {
260 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*k
= NULL
;
262 k
= dns_resource_key_new_redirect(q
->keys
[i
], cname
);
266 r
= dns_question_add(n
, k
);
277 const char *dns_question_first_name(DnsQuestion
*q
) {
285 return DNS_RESOURCE_KEY_NAME(q
->keys
[0]);
288 int dns_question_new_address(DnsQuestion
**ret
, int family
, const char *name
) {
289 _cleanup_(dns_question_unrefp
) DnsQuestion
*q
= NULL
;
295 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
296 return -EAFNOSUPPORT
;
298 q
= dns_question_new(family
== AF_UNSPEC
? 2 : 1);
302 if (family
!= AF_INET6
) {
303 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
305 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
309 r
= dns_question_add(q
, key
);
314 if (family
!= AF_INET
) {
315 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
317 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
321 r
= dns_question_add(q
, key
);
332 int dns_question_new_reverse(DnsQuestion
**ret
, int family
, const union in_addr_union
*a
) {
333 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
334 _cleanup_(dns_question_unrefp
) DnsQuestion
*q
= NULL
;
335 _cleanup_free_
char *reverse
= NULL
;
341 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
342 return -EAFNOSUPPORT
;
344 r
= dns_name_reverse(family
, a
, &reverse
);
348 q
= dns_question_new(1);
352 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, reverse
);
358 r
= dns_question_add(q
, key
);
368 int dns_question_new_service(DnsQuestion
**ret
, const char *name
, bool with_txt
) {
369 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
370 _cleanup_(dns_question_unrefp
) DnsQuestion
*q
= NULL
;
376 q
= dns_question_new(1 + with_txt
);
380 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_SRV
, name
);
384 r
= dns_question_add(q
, key
);
389 dns_resource_key_unref(key
);
390 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_TXT
, name
);
394 r
= dns_question_add(q
, key
);