]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-rr.c
resolved: rework logic so that we can share transactions between queries of different...
[thirdparty/systemd.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 }