]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/dns-type.c
set: add new set_put_strsplit() call
[thirdparty/systemd.git] / src / resolve / dns-type.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2014 Zbigniew Jędrzejewski-Szmek
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <sys/socket.h>
21
22 #include "dns-type.h"
23 #include "parse-util.h"
24 #include "string-util.h"
25
26 typedef const struct {
27 uint16_t type;
28 const char *name;
29 } dns_type;
30
31 static const struct dns_type_name *
32 lookup_dns_type (register const char *str, register unsigned int len);
33
34 #include "dns_type-from-name.h"
35 #include "dns_type-to-name.h"
36
37 int dns_type_from_string(const char *s) {
38 const struct dns_type_name *sc;
39
40 assert(s);
41
42 sc = lookup_dns_type(s, strlen(s));
43 if (sc)
44 return sc->id;
45
46 s = startswith_no_case(s, "TYPE");
47 if (s) {
48 unsigned x;
49
50 if (safe_atou(s, &x) >= 0 &&
51 x <= UINT16_MAX)
52 return (int) x;
53 }
54
55 return _DNS_TYPE_INVALID;
56 }
57
58 bool dns_type_is_pseudo(uint16_t type) {
59
60 /* Checks whether the specified type is a "pseudo-type". What
61 * a "pseudo-type" precisely is, is defined only very weakly,
62 * but apparently entails all RR types that are not actually
63 * stored as RRs on the server and should hence also not be
64 * cached. We use this list primarily to validate NSEC type
65 * bitfields, and to verify what to cache. */
66
67 return IN_SET(type,
68 0, /* A Pseudo RR type, according to RFC 2931 */
69 DNS_TYPE_ANY,
70 DNS_TYPE_AXFR,
71 DNS_TYPE_IXFR,
72 DNS_TYPE_OPT,
73 DNS_TYPE_TSIG,
74 DNS_TYPE_TKEY
75 );
76 }
77
78 bool dns_class_is_pseudo(uint16_t class) {
79 return class == DNS_TYPE_ANY;
80 }
81
82 bool dns_type_is_valid_query(uint16_t type) {
83
84 /* The types valid as questions in packets */
85
86 return !IN_SET(type,
87 0,
88 DNS_TYPE_OPT,
89 DNS_TYPE_TSIG,
90 DNS_TYPE_TKEY,
91
92 /* RRSIG are technically valid as questions, but we refuse doing explicit queries for them, as
93 * they aren't really payload, but signatures for payload, and cannot be validated on their
94 * own. After all they are the signatures, and have no signatures of their own validating
95 * them. */
96 DNS_TYPE_RRSIG);
97 }
98
99 bool dns_type_is_valid_rr(uint16_t type) {
100
101 /* The types valid as RR in packets (but not necessarily
102 * stored on servers). */
103
104 return !IN_SET(type,
105 DNS_TYPE_ANY,
106 DNS_TYPE_AXFR,
107 DNS_TYPE_IXFR);
108 }
109
110 bool dns_class_is_valid_rr(uint16_t class) {
111 return class != DNS_CLASS_ANY;
112 }
113
114 bool dns_type_may_redirect(uint16_t type) {
115 /* The following record types should never be redirected using
116 * CNAME/DNAME RRs. See
117 * <https://tools.ietf.org/html/rfc4035#section-2.5>. */
118
119 if (dns_type_is_pseudo(type))
120 return false;
121
122 return !IN_SET(type,
123 DNS_TYPE_CNAME,
124 DNS_TYPE_DNAME,
125 DNS_TYPE_NSEC3,
126 DNS_TYPE_NSEC,
127 DNS_TYPE_RRSIG,
128 DNS_TYPE_NXT,
129 DNS_TYPE_SIG,
130 DNS_TYPE_KEY);
131 }
132
133 bool dns_type_may_wildcard(uint16_t type) {
134
135 /* The following records may not be expanded from wildcard RRsets */
136
137 if (dns_type_is_pseudo(type))
138 return false;
139
140 return !IN_SET(type,
141 DNS_TYPE_NSEC3,
142 DNS_TYPE_SOA,
143
144 /* Prohibited by https://tools.ietf.org/html/rfc4592#section-4.4 */
145 DNS_TYPE_DNAME);
146 }
147
148 bool dns_type_apex_only(uint16_t type) {
149
150 /* Returns true for all RR types that may only appear signed in a zone apex */
151
152 return IN_SET(type,
153 DNS_TYPE_SOA,
154 DNS_TYPE_NS, /* this one can appear elsewhere, too, but not signed */
155 DNS_TYPE_DNSKEY,
156 DNS_TYPE_NSEC3PARAM);
157 }
158
159 bool dns_type_is_dnssec(uint16_t type) {
160 return IN_SET(type,
161 DNS_TYPE_DS,
162 DNS_TYPE_DNSKEY,
163 DNS_TYPE_RRSIG,
164 DNS_TYPE_NSEC,
165 DNS_TYPE_NSEC3,
166 DNS_TYPE_NSEC3PARAM);
167 }
168
169 bool dns_type_is_obsolete(uint16_t type) {
170 return IN_SET(type,
171 /* Obsoleted by RFC 973 */
172 DNS_TYPE_MD,
173 DNS_TYPE_MF,
174 DNS_TYPE_MAILA,
175
176 /* Kinda obsoleted by RFC 2505 */
177 DNS_TYPE_MB,
178 DNS_TYPE_MG,
179 DNS_TYPE_MR,
180 DNS_TYPE_MINFO,
181 DNS_TYPE_MAILB,
182
183 /* RFC1127 kinda obsoleted this by recommending against its use */
184 DNS_TYPE_WKS,
185
186 /* Declared historical by RFC 6563 */
187 DNS_TYPE_A6,
188
189 /* Obsoleted by DNSSEC-bis */
190 DNS_TYPE_NXT,
191
192 /* RFC 1035 removed support for concepts that needed this from RFC 883 */
193 DNS_TYPE_NULL);
194 }
195
196 bool dns_type_needs_authentication(uint16_t type) {
197
198 /* Returns true for all (non-obsolete) RR types where records are not useful if they aren't
199 * authenticated. I.e. everything that contains crypto keys. */
200
201 return IN_SET(type,
202 DNS_TYPE_CERT,
203 DNS_TYPE_SSHFP,
204 DNS_TYPE_IPSECKEY,
205 DNS_TYPE_DS,
206 DNS_TYPE_DNSKEY,
207 DNS_TYPE_TLSA,
208 DNS_TYPE_CDNSKEY,
209 DNS_TYPE_OPENPGPKEY,
210 DNS_TYPE_CAA);
211 }
212
213 int dns_type_to_af(uint16_t t) {
214 switch (t) {
215
216 case DNS_TYPE_A:
217 return AF_INET;
218
219 case DNS_TYPE_AAAA:
220 return AF_INET6;
221
222 case DNS_TYPE_ANY:
223 return AF_UNSPEC;
224
225 default:
226 return -EINVAL;
227 }
228 }
229
230 const char *dns_class_to_string(uint16_t class) {
231
232 switch (class) {
233
234 case DNS_CLASS_IN:
235 return "IN";
236
237 case DNS_CLASS_ANY:
238 return "ANY";
239 }
240
241 return NULL;
242 }
243
244 int dns_class_from_string(const char *s) {
245
246 if (!s)
247 return _DNS_CLASS_INVALID;
248
249 if (strcaseeq(s, "IN"))
250 return DNS_CLASS_IN;
251 else if (strcaseeq(s, "ANY"))
252 return DNS_CLASS_ANY;
253
254 return _DNS_CLASS_INVALID;
255 }
256
257 const char* tlsa_cert_usage_to_string(uint8_t cert_usage) {
258
259 switch (cert_usage) {
260
261 case 0:
262 return "CA constraint";
263
264 case 1:
265 return "Service certificate constraint";
266
267 case 2:
268 return "Trust anchor assertion";
269
270 case 3:
271 return "Domain-issued certificate";
272
273 case 4 ... 254:
274 return "Unassigned";
275
276 case 255:
277 return "Private use";
278 }
279
280 return NULL; /* clang cannot count that we covered everything */
281 }
282
283 const char* tlsa_selector_to_string(uint8_t selector) {
284 switch (selector) {
285
286 case 0:
287 return "Full Certificate";
288
289 case 1:
290 return "SubjectPublicKeyInfo";
291
292 case 2 ... 254:
293 return "Unassigned";
294
295 case 255:
296 return "Private use";
297 }
298
299 return NULL;
300 }
301
302 const char* tlsa_matching_type_to_string(uint8_t selector) {
303
304 switch (selector) {
305
306 case 0:
307 return "No hash used";
308
309 case 1:
310 return "SHA-256";
311
312 case 2:
313 return "SHA-512";
314
315 case 3 ... 254:
316 return "Unassigned";
317
318 case 255:
319 return "Private use";
320 }
321
322 return NULL;
323 }