chiark / gitweb /
barrier: fix race in test-code
[elogind.git] / src / resolve / resolved-dns-rr.c
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
25 DnsResourceKey* 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
45 DnsResourceKey* 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
62 DnsResourceKey* 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
73 DnsResourceKey* 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
88 int 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
104 int 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
117 int 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
130 unsigned 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
141 int 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
162 DnsResourceRecord* 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
175 DnsResourceRecord* 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
185 DnsResourceRecord* 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
216 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
217         int r;
218
219         assert(a);
220         assert(b);
221
222         r = dns_resource_key_equal(a->key, b->key);
223         if (r <= 0)
224                 return r;
225
226         if (IN_SET(a->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
227                 return dns_name_equal(a->ptr.name, b->ptr.name);
228         else if (a->key->type == DNS_TYPE_HINFO)
229                 return strcasecmp(a->hinfo.cpu, b->hinfo.cpu) == 0 &&
230                        strcasecmp(a->hinfo.os, b->hinfo.os) == 0;
231         else if (a->key->type == DNS_TYPE_A)
232                 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
233         else if (a->key->type == DNS_TYPE_AAAA)
234                 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
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
249                 return a->generic.size == b->generic.size &&
250                         memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
251 }
252
253 const 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
267 const 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 }