networkd: improve error message when udev device can not be found
[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
8bf52d3d
LP
175DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
176 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
177
178 key = dns_resource_key_new(class, type, name);
179 if (!key)
180 return NULL;
181
182 return dns_resource_record_new(key);
183}
184
74b2466e
LP
185DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
186 if (!rr)
187 return NULL;
188
189 assert(rr->n_ref > 0);
190 rr->n_ref++;
191
192 return rr;
193}
194
195DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
196 if (!rr)
197 return NULL;
198
199 assert(rr->n_ref > 0);
200
201 if (rr->n_ref > 1) {
202 rr->n_ref--;
203 return NULL;
204 }
205
faa133f3
LP
206 if (rr->key) {
207 if (IN_SET(rr->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
208 free(rr->ptr.name);
209 else if (rr->key->type == DNS_TYPE_HINFO) {
210 free(rr->hinfo.cpu);
211 free(rr->hinfo.os);
7e8e0422
LP
212 } else if (rr->key->type == DNS_TYPE_SOA) {
213 free(rr->soa.mname);
214 free(rr->soa.rname);
faa133f3
LP
215 } else if (!IN_SET(rr->key->type, DNS_TYPE_A, DNS_TYPE_AAAA))
216 free(rr->generic.data);
322345fd 217
faa133f3
LP
218 dns_resource_key_unref(rr->key);
219 }
322345fd 220
faa133f3 221 free(rr);
322345fd 222
322345fd
LP
223 return NULL;
224}
225
623a4c97
LP
226int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
227 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
228 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
229 _cleanup_free_ char *ptr = NULL;
230 int r;
231
232 assert(ret);
233 assert(address);
234 assert(hostname);
235
236 r = dns_name_reverse(family, address, &ptr);
237 if (r < 0)
238 return r;
239
240 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
241 if (!key)
242 return -ENOMEM;
243
244 ptr = NULL;
245
246 rr = dns_resource_record_new(key);
247 if (!rr)
248 return -ENOMEM;
249
250 rr->ptr.name = strdup(hostname);
251 if (!rr->ptr.name)
252 return -ENOMEM;
253
254 *ret = rr;
255 rr = NULL;
256
257 return 0;
258}
259
322345fd
LP
260int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
261 int r;
262
263 assert(a);
264 assert(b);
265
faa133f3 266 r = dns_resource_key_equal(a->key, b->key);
322345fd
LP
267 if (r <= 0)
268 return r;
269
faa133f3 270 if (IN_SET(a->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
322345fd 271 return dns_name_equal(a->ptr.name, b->ptr.name);
faa133f3 272 else if (a->key->type == DNS_TYPE_HINFO)
322345fd
LP
273 return strcasecmp(a->hinfo.cpu, b->hinfo.cpu) == 0 &&
274 strcasecmp(a->hinfo.os, b->hinfo.os) == 0;
faa133f3 275 else if (a->key->type == DNS_TYPE_A)
322345fd 276 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
faa133f3 277 else if (a->key->type == DNS_TYPE_AAAA)
322345fd 278 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
7e8e0422
LP
279 else if (a->key->type == DNS_TYPE_SOA) {
280 r = dns_name_equal(a->soa.mname, b->soa.mname);
281 if (r <= 0)
282 return r;
283 r = dns_name_equal(a->soa.rname, b->soa.rname);
284 if (r <= 0)
285 return r;
286
287 return a->soa.serial == b->soa.serial &&
288 a->soa.refresh == b->soa.refresh &&
289 a->soa.retry == b->soa.retry &&
290 a->soa.expire == b->soa.expire &&
291 a->soa.minimum == b->soa.minimum;
292 } else
322345fd
LP
293 return a->generic.size == b->generic.size &&
294 memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
295}
296
297const char *dns_class_to_string(uint16_t class) {
298
299 switch (class) {
300
301 case DNS_CLASS_IN:
302 return "IN";
303
304 case DNS_CLASS_ANY:
305 return "ANY";
306 }
307
308 return NULL;
309}
310
311const char *dns_type_to_string(uint16_t type) {
312
313 switch (type) {
314
315 case DNS_TYPE_A:
316 return "A";
317
318 case DNS_TYPE_NS:
319 return "NS";
320
321 case DNS_TYPE_CNAME:
322 return "CNAME";
323
324 case DNS_TYPE_SOA:
325 return "SOA";
326
327 case DNS_TYPE_PTR:
328 return "PTR";
329
330 case DNS_TYPE_HINFO:
331 return "HINFO";
332
333 case DNS_TYPE_MX:
334 return "MX";
335
336 case DNS_TYPE_TXT:
337 return "TXT";
338
339 case DNS_TYPE_AAAA:
340 return "AAAA";
341
342 case DNS_TYPE_SRV:
343 return "SRV";
344
345 case DNS_TYPE_SSHFP:
346 return "SSHFP";
347
348 case DNS_TYPE_DNAME:
349 return "DNAME";
350
351 case DNS_TYPE_ANY:
352 return "ANY";
353
354 case DNS_TYPE_OPT:
355 return "OPT";
356
357 case DNS_TYPE_TKEY:
358 return "TKEY";
359
360 case DNS_TYPE_TSIG:
361 return "TSIG";
362
363 case DNS_TYPE_IXFR:
364 return "IXFR";
365
366 case DNS_TYPE_AXFR:
367 return "AXFR";
368 }
369
370 return NULL;
371}