]>
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
) {
101 for (i
= 0; i
< q
->n_keys
; i
++) {
102 r
= dns_resource_key_match_rr(q
->keys
[i
], rr
);
110 int dns_question_matches_cname(DnsQuestion
*q
, DnsResourceRecord
*rr
) {
119 for (i
= 0; i
< q
->n_keys
; i
++) {
120 r
= dns_resource_key_match_cname(q
->keys
[i
], rr
);
128 int dns_question_is_valid(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_name(DnsQuestion
*q
) {
283 return DNS_RESOURCE_KEY_NAME(q
->keys
[0]);
286 int dns_question_new_address(DnsQuestion
**ret
, int family
, const char *name
) {
287 _cleanup_(dns_question_unrefp
) DnsQuestion
*q
= NULL
;
293 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
294 return -EAFNOSUPPORT
;
296 q
= dns_question_new(family
== AF_UNSPEC
? 2 : 1);
300 if (family
!= AF_INET6
) {
301 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
303 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
307 r
= dns_question_add(q
, key
);
312 if (family
!= AF_INET
) {
313 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
315 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
319 r
= dns_question_add(q
, key
);
330 int dns_question_new_reverse(DnsQuestion
**ret
, int family
, const union in_addr_union
*a
) {
331 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
332 _cleanup_(dns_question_unrefp
) DnsQuestion
*q
= NULL
;
333 _cleanup_free_
char *reverse
= NULL
;
339 if (!IN_SET(family
, AF_INET
, AF_INET6
, AF_UNSPEC
))
340 return -EAFNOSUPPORT
;
342 r
= dns_name_reverse(family
, a
, &reverse
);
346 q
= dns_question_new(1);
350 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, reverse
);
356 r
= dns_question_add(q
, key
);
366 int dns_question_new_service(DnsQuestion
**ret
, const char *name
, bool with_txt
) {
367 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
368 _cleanup_(dns_question_unrefp
) DnsQuestion
*q
= NULL
;
374 q
= dns_question_new(1 + with_txt
);
378 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_SRV
, name
);
382 r
= dns_question_add(q
, key
);
387 dns_resource_key_unref(key
);
388 key
= dns_resource_key_new(DNS_CLASS_IN
, DNS_TYPE_TXT
, name
);
392 r
= dns_question_add(q
, key
);