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