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