chiark / gitweb /
c9b564b544135952c06e9a88b3e997ac6848c20f
[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 (!IN_SET(rr->key->type, DNS_TYPE_A, DNS_TYPE_AAAA))
203                         free(rr->generic.data);
204
205                 dns_resource_key_unref(rr->key);
206         }
207
208         free(rr);
209
210         return NULL;
211 }
212
213 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
214         int r;
215
216         assert(a);
217         assert(b);
218
219         r = dns_resource_key_equal(a->key, b->key);
220         if (r <= 0)
221                 return r;
222
223         if (IN_SET(a->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
224                 return dns_name_equal(a->ptr.name, b->ptr.name);
225         else if (a->key->type == DNS_TYPE_HINFO)
226                 return strcasecmp(a->hinfo.cpu, b->hinfo.cpu) == 0 &&
227                        strcasecmp(a->hinfo.os, b->hinfo.os) == 0;
228         else if (a->key->type == DNS_TYPE_A)
229                 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
230         else if (a->key->type == DNS_TYPE_AAAA)
231                 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
232         else
233                 return a->generic.size == b->generic.size &&
234                         memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
235 }
236
237 const char *dns_class_to_string(uint16_t class) {
238
239         switch (class) {
240
241         case DNS_CLASS_IN:
242                 return "IN";
243
244         case DNS_CLASS_ANY:
245                 return "ANY";
246         }
247
248         return NULL;
249 }
250
251 const char *dns_type_to_string(uint16_t type) {
252
253         switch (type) {
254
255         case DNS_TYPE_A:
256                 return "A";
257
258         case DNS_TYPE_NS:
259                 return "NS";
260
261         case DNS_TYPE_CNAME:
262                 return "CNAME";
263
264         case DNS_TYPE_SOA:
265                 return "SOA";
266
267         case DNS_TYPE_PTR:
268                 return "PTR";
269
270         case DNS_TYPE_HINFO:
271                 return "HINFO";
272
273         case DNS_TYPE_MX:
274                 return "MX";
275
276         case DNS_TYPE_TXT:
277                 return "TXT";
278
279         case DNS_TYPE_AAAA:
280                 return "AAAA";
281
282         case DNS_TYPE_SRV:
283                 return "SRV";
284
285         case DNS_TYPE_SSHFP:
286                 return "SSHFP";
287
288         case DNS_TYPE_DNAME:
289                 return "DNAME";
290
291         case DNS_TYPE_ANY:
292                 return "ANY";
293
294         case DNS_TYPE_OPT:
295                 return "OPT";
296
297         case DNS_TYPE_TKEY:
298                 return "TKEY";
299
300         case DNS_TYPE_TSIG:
301                 return "TSIG";
302
303         case DNS_TYPE_IXFR:
304                 return "IXFR";
305
306         case DNS_TYPE_AXFR:
307                 return "AXFR";
308         }
309
310         return NULL;
311 }