]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-question.c
question: drop dns_question_is_superset() which we don't use anymore
[thirdparty/systemd.git] / src / resolve / resolved-dns-question.c
CommitLineData
faa133f3
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
b5efdb8a 22#include "alloc-util.h"
4ad7f276 23#include "dns-domain.h"
b5efdb8a 24#include "resolved-dns-question.h"
faa133f3
LP
25
26DnsQuestion *dns_question_new(unsigned n) {
27 DnsQuestion *q;
28
29 assert(n > 0);
30
31 q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n);
32 if (!q)
33 return NULL;
34
35 q->n_ref = 1;
36 q->n_allocated = n;
37
38 return q;
39}
40
41DnsQuestion *dns_question_ref(DnsQuestion *q) {
42 if (!q)
43 return NULL;
44
45 assert(q->n_ref > 0);
46 q->n_ref++;
47 return q;
48}
49
50DnsQuestion *dns_question_unref(DnsQuestion *q) {
51 if (!q)
52 return NULL;
53
54 assert(q->n_ref > 0);
55
56 if (q->n_ref == 1) {
57 unsigned i;
58
59 for (i = 0; i < q->n_keys; i++)
60 dns_resource_key_unref(q->keys[i]);
61 free(q);
62 } else
63 q->n_ref--;
64
65 return NULL;
66}
67
68int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
7e8e0422
LP
69 unsigned i;
70 int r;
71
faa133f3
LP
72 assert(key);
73
8013e860
LP
74 if (!q)
75 return -ENOSPC;
76
7e8e0422
LP
77 for (i = 0; i < q->n_keys; i++) {
78 r = dns_resource_key_equal(q->keys[i], key);
79 if (r < 0)
80 return r;
81 if (r > 0)
82 return 0;
83 }
84
faa133f3
LP
85 if (q->n_keys >= q->n_allocated)
86 return -ENOSPC;
87
88 q->keys[q->n_keys++] = dns_resource_key_ref(key);
89 return 0;
90}
91
92int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr) {
93 unsigned i;
94 int r;
95
faa133f3
LP
96 assert(rr);
97
8013e860
LP
98 if (!q)
99 return 0;
100
faa133f3
LP
101 for (i = 0; i < q->n_keys; i++) {
102 r = dns_resource_key_match_rr(q->keys[i], rr);
103 if (r != 0)
104 return r;
105 }
106
107 return 0;
108}
109
110int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr) {
111 unsigned i;
112 int r;
113
faa133f3
LP
114 assert(rr);
115
8013e860
LP
116 if (!q)
117 return 0;
118
faa133f3
LP
119 for (i = 0; i < q->n_keys; i++) {
120 r = dns_resource_key_match_cname(q->keys[i], rr);
121 if (r != 0)
122 return r;
123 }
124
34b9656f 125 return 0;
faa133f3
LP
126}
127
128int dns_question_is_valid(DnsQuestion *q) {
129 const char *name;
130 unsigned i;
131 int r;
132
8013e860
LP
133 if (!q)
134 return 0;
faa133f3
LP
135
136 if (q->n_keys <= 0)
137 return 0;
138
139 if (q->n_keys > 65535)
140 return 0;
141
142 name = DNS_RESOURCE_KEY_NAME(q->keys[0]);
143 if (!name)
144 return 0;
145
146 /* Check that all keys in this question bear the same name */
147 for (i = 1; i < q->n_keys; i++) {
34b9656f
LP
148 assert(q->keys[i]);
149
faa133f3
LP
150 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
151 if (r <= 0)
152 return r;
153 }
154
155 return 1;
156}
157
1086182d
LP
158int dns_question_contains(DnsQuestion *a, DnsResourceKey *k) {
159 unsigned j;
160 int r;
161
1086182d
LP
162 assert(k);
163
8013e860
LP
164 if (!a)
165 return 0;
166
1086182d
LP
167 for (j = 0; j < a->n_keys; j++) {
168 r = dns_resource_key_equal(a->keys[j], k);
169 if (r != 0)
170 return r;
171 }
172
173 return 0;
174}
175
176int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
177 unsigned j;
178 int r;
179
8013e860
LP
180 if (!a)
181 return !b || b->n_keys == 0;
182 if (!b)
183 return a->n_keys == 0;
1086182d
LP
184
185 /* Checks if all keys in a are also contained b, and vice versa */
186
187 for (j = 0; j < a->n_keys; j++) {
188 r = dns_question_contains(b, a->keys[j]);
189 if (r <= 0)
190 return r;
191 }
192
193 for (j = 0; j < b->n_keys; j++) {
194 r = dns_question_contains(a, b->keys[j]);
195 if (r <= 0)
196 return r;
197 }
198
199 return 1;
200}
201
36d9205d 202int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) {
faa133f3
LP
203 _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
204 bool same = true;
205 unsigned i;
206 int r;
207
36d9205d 208 assert(cname);
faa133f3
LP
209 assert(ret);
210
8013e860
LP
211 if (!q) {
212 n = dns_question_new(0);
213 if (!n)
214 return -ENOMEM;
215
216 *ret = n;
217 n = 0;
218 return 0;
219 }
220
faa133f3 221 for (i = 0; i < q->n_keys; i++) {
36d9205d 222 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), cname->cname.name);
faa133f3
LP
223 if (r < 0)
224 return r;
225
226 if (r == 0) {
227 same = false;
228 break;
229 }
230 }
231
232 if (same) {
233 /* Shortcut, the names are already right */
234 *ret = dns_question_ref(q);
235 return 0;
236 }
237
238 n = dns_question_new(q->n_keys);
239 if (!n)
240 return -ENOMEM;
241
242 /* Create a new question, and patch in the new name */
34b9656f 243 for (i = 0; i < q->n_keys; i++) {
faa133f3
LP
244 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
245
36d9205d 246 k = dns_resource_key_new_redirect(q->keys[i], cname);
faa133f3
LP
247 if (!k)
248 return -ENOMEM;
249
250 r = dns_question_add(n, k);
251 if (r < 0)
252 return r;
253 }
254
255 *ret = n;
256 n = NULL;
257
258 return 1;
259}
45ec7efb
LP
260
261const char *dns_question_name(DnsQuestion *q) {
262 assert(q);
263
264 if (q->n_keys < 1)
265 return NULL;
266
267 return DNS_RESOURCE_KEY_NAME(q->keys[0]);
268}
269
270int dns_question_new_address(DnsQuestion **ret, int family, const char *name) {
271 _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
272 int r;
273
274 assert(ret);
275 assert(name);
276
277 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
278 return -EAFNOSUPPORT;
279
280 q = dns_question_new(family == AF_UNSPEC ? 2 : 1);
281 if (!q)
282 return -ENOMEM;
283
284 if (family != AF_INET6) {
285 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
286
287 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, name);
288 if (!key)
289 return -ENOMEM;
290
291 r = dns_question_add(q, key);
292 if (r < 0)
293 return r;
294 }
295
296 if (family != AF_INET) {
297 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
298
299 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
300 if (!key)
301 return -ENOMEM;
302
303 r = dns_question_add(q, key);
304 if (r < 0)
305 return r;
306 }
307
308 *ret = q;
309 q = NULL;
310
311 return 0;
312}
313
314int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a) {
315 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
316 _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
317 _cleanup_free_ char *reverse = NULL;
318 int r;
319
320 assert(ret);
321 assert(a);
322
323 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
324 return -EAFNOSUPPORT;
325
326 r = dns_name_reverse(family, a, &reverse);
327 if (r < 0)
328 return r;
329
330 q = dns_question_new(1);
331 if (!q)
332 return -ENOMEM;
333
334 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
335 if (!key)
336 return -ENOMEM;
337
338 reverse = NULL;
339
340 r = dns_question_add(q, key);
341 if (r < 0)
342 return r;
343
344 *ret = q;
345 q = NULL;
346
347 return 0;
348}
349
350int dns_question_new_service(DnsQuestion **ret, const char *name, bool with_txt) {
351 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
352 _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
353 int r;
354
355 assert(ret);
356 assert(name);
357
358 q = dns_question_new(1 + with_txt);
359 if (!q)
360 return -ENOMEM;
361
362 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_SRV, name);
363 if (!key)
364 return -ENOMEM;
365
366 r = dns_question_add(q, key);
367 if (r < 0)
368 return r;
369
370 if (with_txt) {
371 dns_resource_key_unref(key);
372 key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_TXT, name);
373 if (!key)
374 return -ENOMEM;
375
376 r = dns_question_add(q, key);
377 if (r < 0)
378 return r;
379 }
380
381 *ret = q;
382 q = NULL;
383
384 return 0;
385}