resolved: rework logic so that we can share transactions between queries of different...
[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);
202 } else if (!IN_SET(rr->key->type, DNS_TYPE_A, DNS_TYPE_AAAA))
203 free(rr->generic.data);
322345fd 204
faa133f3
LP
205 dns_resource_key_unref(rr->key);
206 }
322345fd 207
faa133f3 208 free(rr);
322345fd 209
322345fd
LP
210 return NULL;
211}
212
213int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
214 int r;
215
216 assert(a);
217 assert(b);
218
faa133f3 219 r = dns_resource_key_equal(a->key, b->key);
322345fd
LP
220 if (r <= 0)
221 return r;
222
faa133f3 223 if (IN_SET(a->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
322345fd 224 return dns_name_equal(a->ptr.name, b->ptr.name);
faa133f3 225 else if (a->key->type == DNS_TYPE_HINFO)
322345fd
LP
226 return strcasecmp(a->hinfo.cpu, b->hinfo.cpu) == 0 &&
227 strcasecmp(a->hinfo.os, b->hinfo.os) == 0;
faa133f3 228 else if (a->key->type == DNS_TYPE_A)
322345fd 229 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
faa133f3 230 else if (a->key->type == DNS_TYPE_AAAA)
322345fd
LP
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
237const 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
251const 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}