]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/resolve/resolved-dns-rr.c
TODO
[thirdparty/systemd.git] / src / resolve / resolved-dns-rr.c
... / ...
CommitLineData
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-domain.h"
23#include "resolved-dns-rr.h"
24
25DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
26 DnsResourceKey *k;
27 size_t l;
28
29 assert(name);
30
31 l = strlen(name);
32 k = malloc0(sizeof(DnsResourceKey) + l + 1);
33 if (!k)
34 return NULL;
35
36 k->n_ref = 1;
37 k->class = class;
38 k->type = type;
39
40 strcpy((char*) k + sizeof(DnsResourceKey), name);
41
42 return k;
43}
44
45DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
46 DnsResourceKey *k;
47
48 assert(name);
49
50 k = new0(DnsResourceKey, 1);
51 if (!k)
52 return NULL;
53
54 k->n_ref = 1;
55 k->class = class;
56 k->type = type;
57 k->_name = name;
58
59 return k;
60}
61
62DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
63
64 if (!k)
65 return NULL;
66
67 assert(k->n_ref > 0);
68 k->n_ref++;
69
70 return k;
71}
72
73DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
74 if (!k)
75 return NULL;
76
77 assert(k->n_ref > 0);
78
79 if (k->n_ref == 1) {
80 free(k->_name);
81 free(k);
82 } else
83 k->n_ref--;
84
85 return NULL;
86}
87
88int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
89 int r;
90
91 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
92 if (r <= 0)
93 return r;
94
95 if (a->class != b->class)
96 return 0;
97
98 if (a->type != b->type)
99 return 0;
100
101 return 1;
102}
103
104int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
105 assert(key);
106 assert(rr);
107
108 if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
109 return 0;
110
111 if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
112 return 0;
113
114 return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
115}
116
117int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr) {
118 assert(key);
119 assert(rr);
120
121 if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
122 return 0;
123
124 if (rr->key->type != DNS_TYPE_CNAME)
125 return 0;
126
127 return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
128}
129
130unsigned long dns_resource_key_hash_func(const void *i, const uint8_t hash_key[HASH_KEY_SIZE]) {
131 const DnsResourceKey *k = i;
132 unsigned long ul;
133
134 ul = dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), hash_key);
135 ul = ul * hash_key[0] + ul + k->class;
136 ul = ul * hash_key[1] + ul + k->type;
137
138 return ul;
139}
140
141int dns_resource_key_compare_func(const void *a, const void *b) {
142 const DnsResourceKey *x = a, *y = b;
143 int ret;
144
145 ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
146 if (ret != 0)
147 return ret;
148
149 if (x->type < y->type)
150 return -1;
151 if (x->type > y->type)
152 return 1;
153
154 if (x->class < y->class)
155 return -1;
156 if (x->class > y->class)
157 return 1;
158
159 return 0;
160}
161
162DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
163 DnsResourceRecord *rr;
164
165 rr = new0(DnsResourceRecord, 1);
166 if (!rr)
167 return NULL;
168
169 rr->n_ref = 1;
170 rr->key = dns_resource_key_ref(key);
171
172 return rr;
173}
174
175DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
176 if (!rr)
177 return NULL;
178
179 assert(rr->n_ref > 0);
180 rr->n_ref++;
181
182 return rr;
183}
184
185DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
186 if (!rr)
187 return NULL;
188
189 assert(rr->n_ref > 0);
190
191 if (rr->n_ref > 1) {
192 rr->n_ref--;
193 return NULL;
194 }
195
196 if (rr->key) {
197 if (IN_SET(rr->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
198 free(rr->ptr.name);
199 else if (rr->key->type == DNS_TYPE_HINFO) {
200 free(rr->hinfo.cpu);
201 free(rr->hinfo.os);
202 } else if (rr->key->type == DNS_TYPE_SOA) {
203 free(rr->soa.mname);
204 free(rr->soa.rname);
205 } else if (!IN_SET(rr->key->type, DNS_TYPE_A, DNS_TYPE_AAAA))
206 free(rr->generic.data);
207
208 dns_resource_key_unref(rr->key);
209 }
210
211 free(rr);
212
213 return NULL;
214}
215
216int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
217 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
218 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
219 _cleanup_free_ char *ptr = NULL;
220 int r;
221
222 assert(ret);
223 assert(address);
224 assert(hostname);
225
226 r = dns_name_reverse(family, address, &ptr);
227 if (r < 0)
228 return r;
229
230 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
231 if (!key)
232 return -ENOMEM;
233
234 ptr = NULL;
235
236 rr = dns_resource_record_new(key);
237 if (!rr)
238 return -ENOMEM;
239
240 rr->ptr.name = strdup(hostname);
241 if (!rr->ptr.name)
242 return -ENOMEM;
243
244 *ret = rr;
245 rr = NULL;
246
247 return 0;
248}
249
250int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
251 int r;
252
253 assert(a);
254 assert(b);
255
256 r = dns_resource_key_equal(a->key, b->key);
257 if (r <= 0)
258 return r;
259
260 if (IN_SET(a->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
261 return dns_name_equal(a->ptr.name, b->ptr.name);
262 else if (a->key->type == DNS_TYPE_HINFO)
263 return strcasecmp(a->hinfo.cpu, b->hinfo.cpu) == 0 &&
264 strcasecmp(a->hinfo.os, b->hinfo.os) == 0;
265 else if (a->key->type == DNS_TYPE_A)
266 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
267 else if (a->key->type == DNS_TYPE_AAAA)
268 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
269 else if (a->key->type == DNS_TYPE_SOA) {
270 r = dns_name_equal(a->soa.mname, b->soa.mname);
271 if (r <= 0)
272 return r;
273 r = dns_name_equal(a->soa.rname, b->soa.rname);
274 if (r <= 0)
275 return r;
276
277 return a->soa.serial == b->soa.serial &&
278 a->soa.refresh == b->soa.refresh &&
279 a->soa.retry == b->soa.retry &&
280 a->soa.expire == b->soa.expire &&
281 a->soa.minimum == b->soa.minimum;
282 } else
283 return a->generic.size == b->generic.size &&
284 memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
285}
286
287const char *dns_class_to_string(uint16_t class) {
288
289 switch (class) {
290
291 case DNS_CLASS_IN:
292 return "IN";
293
294 case DNS_CLASS_ANY:
295 return "ANY";
296 }
297
298 return NULL;
299}
300
301const char *dns_type_to_string(uint16_t type) {
302
303 switch (type) {
304
305 case DNS_TYPE_A:
306 return "A";
307
308 case DNS_TYPE_NS:
309 return "NS";
310
311 case DNS_TYPE_CNAME:
312 return "CNAME";
313
314 case DNS_TYPE_SOA:
315 return "SOA";
316
317 case DNS_TYPE_PTR:
318 return "PTR";
319
320 case DNS_TYPE_HINFO:
321 return "HINFO";
322
323 case DNS_TYPE_MX:
324 return "MX";
325
326 case DNS_TYPE_TXT:
327 return "TXT";
328
329 case DNS_TYPE_AAAA:
330 return "AAAA";
331
332 case DNS_TYPE_SRV:
333 return "SRV";
334
335 case DNS_TYPE_SSHFP:
336 return "SSHFP";
337
338 case DNS_TYPE_DNAME:
339 return "DNAME";
340
341 case DNS_TYPE_ANY:
342 return "ANY";
343
344 case DNS_TYPE_OPT:
345 return "OPT";
346
347 case DNS_TYPE_TKEY:
348 return "TKEY";
349
350 case DNS_TYPE_TSIG:
351 return "TSIG";
352
353 case DNS_TYPE_IXFR:
354 return "IXFR";
355
356 case DNS_TYPE_AXFR:
357 return "AXFR";
358 }
359
360 return NULL;
361}