chiark / gitweb /
resolved: discard more invalid llmnr messages
[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_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
217         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
218         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
219         _cleanup_free_ char *ptr = NULL;
220         int r;
221
222         assert(ret);
223         assert(address);
224         assert(hostname);
225
226         r = dns_name_reverse(family, address, &ptr);
227         if (r < 0)
228                 return r;
229
230         key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
231         if (!key)
232                 return -ENOMEM;
233
234         ptr = NULL;
235
236         rr = dns_resource_record_new(key);
237         if (!rr)
238                 return -ENOMEM;
239
240         rr->ptr.name = strdup(hostname);
241         if (!rr->ptr.name)
242                 return -ENOMEM;
243
244         *ret = rr;
245         rr = NULL;
246
247         return 0;
248 }
249
250 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
251         int r;
252
253         assert(a);
254         assert(b);
255
256         r = dns_resource_key_equal(a->key, b->key);
257         if (r <= 0)
258                 return r;
259
260         if (IN_SET(a->key->type, DNS_TYPE_PTR, DNS_TYPE_NS, DNS_TYPE_CNAME))
261                 return dns_name_equal(a->ptr.name, b->ptr.name);
262         else if (a->key->type == DNS_TYPE_HINFO)
263                 return strcasecmp(a->hinfo.cpu, b->hinfo.cpu) == 0 &&
264                        strcasecmp(a->hinfo.os, b->hinfo.os) == 0;
265         else if (a->key->type == DNS_TYPE_A)
266                 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
267         else if (a->key->type == DNS_TYPE_AAAA)
268                 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
269         else if (a->key->type == DNS_TYPE_SOA) {
270                 r = dns_name_equal(a->soa.mname, b->soa.mname);
271                 if (r <= 0)
272                         return r;
273                 r = dns_name_equal(a->soa.rname, b->soa.rname);
274                 if (r <= 0)
275                         return r;
276
277                 return a->soa.serial  == b->soa.serial &&
278                        a->soa.refresh == b->soa.refresh &&
279                        a->soa.retry   == b->soa.retry &&
280                        a->soa.expire  == b->soa.expire &&
281                        a->soa.minimum == b->soa.minimum;
282         } else
283                 return a->generic.size == b->generic.size &&
284                         memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
285 }
286
287 const char *dns_class_to_string(uint16_t class) {
288
289         switch (class) {
290
291         case DNS_CLASS_IN:
292                 return "IN";
293
294         case DNS_CLASS_ANY:
295                 return "ANY";
296         }
297
298         return NULL;
299 }
300
301 const char *dns_type_to_string(uint16_t type) {
302
303         switch (type) {
304
305         case DNS_TYPE_A:
306                 return "A";
307
308         case DNS_TYPE_NS:
309                 return "NS";
310
311         case DNS_TYPE_CNAME:
312                 return "CNAME";
313
314         case DNS_TYPE_SOA:
315                 return "SOA";
316
317         case DNS_TYPE_PTR:
318                 return "PTR";
319
320         case DNS_TYPE_HINFO:
321                 return "HINFO";
322
323         case DNS_TYPE_MX:
324                 return "MX";
325
326         case DNS_TYPE_TXT:
327                 return "TXT";
328
329         case DNS_TYPE_AAAA:
330                 return "AAAA";
331
332         case DNS_TYPE_SRV:
333                 return "SRV";
334
335         case DNS_TYPE_SSHFP:
336                 return "SSHFP";
337
338         case DNS_TYPE_DNAME:
339                 return "DNAME";
340
341         case DNS_TYPE_ANY:
342                 return "ANY";
343
344         case DNS_TYPE_OPT:
345                 return "OPT";
346
347         case DNS_TYPE_TKEY:
348                 return "TKEY";
349
350         case DNS_TYPE_TSIG:
351                 return "TSIG";
352
353         case DNS_TYPE_IXFR:
354                 return "IXFR";
355
356         case DNS_TYPE_AXFR:
357                 return "AXFR";
358         }
359
360         return NULL;
361 }