]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-question.c
Merge pull request #147 from poettering/cmsg
[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
22#include "resolved-dns-question.h"
23#include "resolved-dns-domain.h"
24
25DnsQuestion *dns_question_new(unsigned n) {
26 DnsQuestion *q;
27
28 assert(n > 0);
29
30 q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n);
31 if (!q)
32 return NULL;
33
34 q->n_ref = 1;
35 q->n_allocated = n;
36
37 return q;
38}
39
40DnsQuestion *dns_question_ref(DnsQuestion *q) {
41 if (!q)
42 return NULL;
43
44 assert(q->n_ref > 0);
45 q->n_ref++;
46 return q;
47}
48
49DnsQuestion *dns_question_unref(DnsQuestion *q) {
50 if (!q)
51 return NULL;
52
53 assert(q->n_ref > 0);
54
55 if (q->n_ref == 1) {
56 unsigned i;
57
58 for (i = 0; i < q->n_keys; i++)
59 dns_resource_key_unref(q->keys[i]);
60 free(q);
61 } else
62 q->n_ref--;
63
64 return NULL;
65}
66
67int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
7e8e0422
LP
68 unsigned i;
69 int r;
70
faa133f3
LP
71 assert(q);
72 assert(key);
73
7e8e0422
LP
74 for (i = 0; i < q->n_keys; i++) {
75 r = dns_resource_key_equal(q->keys[i], key);
76 if (r < 0)
77 return r;
78 if (r > 0)
79 return 0;
80 }
81
faa133f3
LP
82 if (q->n_keys >= q->n_allocated)
83 return -ENOSPC;
84
85 q->keys[q->n_keys++] = dns_resource_key_ref(key);
86 return 0;
87}
88
89int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr) {
90 unsigned i;
91 int r;
92
93 assert(q);
94 assert(rr);
95
96 for (i = 0; i < q->n_keys; i++) {
97 r = dns_resource_key_match_rr(q->keys[i], rr);
98 if (r != 0)
99 return r;
100 }
101
102 return 0;
103}
104
105int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr) {
106 unsigned i;
107 int r;
108
109 assert(q);
110 assert(rr);
111
112 for (i = 0; i < q->n_keys; i++) {
113 r = dns_resource_key_match_cname(q->keys[i], rr);
114 if (r != 0)
115 return r;
116 }
117
34b9656f 118 return 0;
faa133f3
LP
119}
120
121int dns_question_is_valid(DnsQuestion *q) {
122 const char *name;
123 unsigned i;
124 int r;
125
126 assert(q);
127
128 if (q->n_keys <= 0)
129 return 0;
130
131 if (q->n_keys > 65535)
132 return 0;
133
134 name = DNS_RESOURCE_KEY_NAME(q->keys[0]);
135 if (!name)
136 return 0;
137
138 /* Check that all keys in this question bear the same name */
139 for (i = 1; i < q->n_keys; i++) {
34b9656f
LP
140 assert(q->keys[i]);
141
faa133f3
LP
142 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
143 if (r <= 0)
144 return r;
145 }
146
147 return 1;
148}
149
150int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other) {
151 unsigned j;
152 int r;
153
154 assert(q);
155 assert(other);
156
157 /* Checks if all keys in "other" are also contained in "q" */
158
159 for (j = 0; j < other->n_keys; j++) {
160 DnsResourceKey *b = other->keys[j];
161 bool found = false;
162 unsigned i;
163
164 for (i = 0; i < q->n_keys; i++) {
165 DnsResourceKey *a = q->keys[i];
166
167 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
168 if (r < 0)
169 return r;
170
171 if (r == 0)
172 continue;
173
174 if (a->class != b->class && a->class != DNS_CLASS_ANY)
175 continue;
176
177 if (a->type != b->type && a->type != DNS_TYPE_ANY)
178 continue;
179
180 found = true;
181 break;
182 }
183
184 if (!found)
185 return 0;
186 }
187
188 return 1;
189}
190
191int dns_question_cname_redirect(DnsQuestion *q, const char *name, DnsQuestion **ret) {
192 _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
193 bool same = true;
194 unsigned i;
195 int r;
196
197 assert(q);
198 assert(name);
199 assert(ret);
200
201 for (i = 0; i < q->n_keys; i++) {
202 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
203 if (r < 0)
204 return r;
205
206 if (r == 0) {
207 same = false;
208 break;
209 }
210 }
211
212 if (same) {
213 /* Shortcut, the names are already right */
214 *ret = dns_question_ref(q);
215 return 0;
216 }
217
218 n = dns_question_new(q->n_keys);
219 if (!n)
220 return -ENOMEM;
221
222 /* Create a new question, and patch in the new name */
34b9656f 223 for (i = 0; i < q->n_keys; i++) {
faa133f3
LP
224 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
225
226 k = dns_resource_key_new(q->keys[i]->class, q->keys[i]->type, name);
227 if (!k)
228 return -ENOMEM;
229
230 r = dns_question_add(n, k);
231 if (r < 0)
232 return r;
233 }
234
235 *ret = n;
236 n = NULL;
237
238 return 1;
239}
b914e211
LP
240
241int dns_question_endswith(DnsQuestion *q, const char *suffix) {
242 unsigned i;
243
244 assert(q);
245 assert(suffix);
246
247 for (i = 0; i < q->n_keys; i++) {
248 int k;
249
250 k = dns_name_endswith(DNS_RESOURCE_KEY_NAME(q->keys[i]), suffix);
251 if (k <= 0)
252 return k;
253 }
254
255 return 1;
256}
257
258int dns_question_extract_reverse_address(DnsQuestion *q, int *family, union in_addr_union *address) {
259 unsigned i;
260
261 assert(q);
262 assert(family);
263 assert(address);
264
265 for (i = 0; i < q->n_keys; i++) {
266 int k;
267
268 k = dns_name_address(DNS_RESOURCE_KEY_NAME(q->keys[i]), family, address);
269 if (k != 0)
270 return k;
271 }
272
273 return 0;
274}