barrier: fix race in test-code
[thirdparty/systemd.git] / src / resolve / resolved-dns-rr.c
CommitLineData
74b2466e
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
322345fd 22#include "resolved-dns-domain.h"
74b2466e
LP
23#include "resolved-dns-rr.h"
24
faa133f3
LP
25DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
26 DnsResourceKey *k;
27 size_t l;
74b2466e 28
faa133f3
LP
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));
74b2466e
LP
128}
129
322345fd
LP
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
faa133f3 134 ul = dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), hash_key);
322345fd
LP
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
faa133f3 145 ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
322345fd
LP
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
faa133f3 162DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
74b2466e
LP
163 DnsResourceRecord *rr;
164
165 rr = new0(DnsResourceRecord, 1);
166 if (!rr)
167 return NULL;
168
169 rr->n_ref = 1;
faa133f3
LP
170 rr->key = dns_resource_key_ref(key);
171
74b2466e
LP
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
faa133f3
LP
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);
7e8e0422
LP
202 } else if (rr->key->type == DNS_TYPE_SOA) {
203 free(rr->soa.mname);
204 free(rr->soa.rname);
faa133f3
LP
205 } else if (!IN_SET(rr->key->type, DNS_TYPE_A, DNS_TYPE_AAAA))
206 free(rr->generic.data);
322345fd 207
faa133f3
LP
208 dns_resource_key_unref(rr->key);
209 }
322345fd 210
faa133f3 211 free(rr);
322345fd 212
322345fd
LP
213 return NULL;
214}
215
216int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
217 int r;
218
219 assert(a);
220 assert(b);
221
faa133f3 222 r = dns_resource_key_equal(a->key, b->key);
322345fd
LP
223 if (r <= 0)
224 return r;
225
faa133f3 226 if (IN_SET(a->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
322345fd 227 return dns_name_equal(a->ptr.name, b->ptr.name);
faa133f3 228 else if (a->key->type == DNS_TYPE_HINFO)
322345fd
LP
229 return strcasecmp(a->hinfo.cpu, b->hinfo.cpu) == 0 &&
230 strcasecmp(a->hinfo.os, b->hinfo.os) == 0;
faa133f3 231 else if (a->key->type == DNS_TYPE_A)
322345fd 232 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
faa133f3 233 else if (a->key->type == DNS_TYPE_AAAA)
322345fd 234 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
7e8e0422
LP
235 else if (a->key->type == DNS_TYPE_SOA) {
236 r = dns_name_equal(a->soa.mname, b->soa.mname);
237 if (r <= 0)
238 return r;
239 r = dns_name_equal(a->soa.rname, b->soa.rname);
240 if (r <= 0)
241 return r;
242
243 return a->soa.serial == b->soa.serial &&
244 a->soa.refresh == b->soa.refresh &&
245 a->soa.retry == b->soa.retry &&
246 a->soa.expire == b->soa.expire &&
247 a->soa.minimum == b->soa.minimum;
248 } else
322345fd
LP
249 return a->generic.size == b->generic.size &&
250 memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
251}
252
253const char *dns_class_to_string(uint16_t class) {
254
255 switch (class) {
256
257 case DNS_CLASS_IN:
258 return "IN";
259
260 case DNS_CLASS_ANY:
261 return "ANY";
262 }
263
264 return NULL;
265}
266
267const char *dns_type_to_string(uint16_t type) {
268
269 switch (type) {
270
271 case DNS_TYPE_A:
272 return "A";
273
274 case DNS_TYPE_NS:
275 return "NS";
276
277 case DNS_TYPE_CNAME:
278 return "CNAME";
279
280 case DNS_TYPE_SOA:
281 return "SOA";
282
283 case DNS_TYPE_PTR:
284 return "PTR";
285
286 case DNS_TYPE_HINFO:
287 return "HINFO";
288
289 case DNS_TYPE_MX:
290 return "MX";
291
292 case DNS_TYPE_TXT:
293 return "TXT";
294
295 case DNS_TYPE_AAAA:
296 return "AAAA";
297
298 case DNS_TYPE_SRV:
299 return "SRV";
300
301 case DNS_TYPE_SSHFP:
302 return "SSHFP";
303
304 case DNS_TYPE_DNAME:
305 return "DNAME";
306
307 case DNS_TYPE_ANY:
308 return "ANY";
309
310 case DNS_TYPE_OPT:
311 return "OPT";
312
313 case DNS_TYPE_TKEY:
314 return "TKEY";
315
316 case DNS_TYPE_TSIG:
317 return "TSIG";
318
319 case DNS_TYPE_IXFR:
320 return "IXFR";
321
322 case DNS_TYPE_AXFR:
323 return "AXFR";
324 }
325
326 return NULL;
327}