]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/dns-type.c
Merge pull request #2495 from heftig/master
[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 int dns_type_to_af(uint16_t t) {
197 switch (t) {
198
199 case DNS_TYPE_A:
200 return AF_INET;
201
202 case DNS_TYPE_AAAA:
203 return AF_INET6;
204
205 case DNS_TYPE_ANY:
206 return AF_UNSPEC;
207
208 default:
209 return -EINVAL;
210 }
211 }
212
213 const char *dns_class_to_string(uint16_t class) {
214
215 switch (class) {
216
217 case DNS_CLASS_IN:
218 return "IN";
219
220 case DNS_CLASS_ANY:
221 return "ANY";
222 }
223
224 return NULL;
225 }
226
227 int dns_class_from_string(const char *s) {
228
229 if (!s)
230 return _DNS_CLASS_INVALID;
231
232 if (strcaseeq(s, "IN"))
233 return DNS_CLASS_IN;
234 else if (strcaseeq(s, "ANY"))
235 return DNS_CLASS_ANY;
236
237 return _DNS_CLASS_INVALID;
238 }
239
240 const char* tlsa_cert_usage_to_string(uint8_t cert_usage) {
241
242 switch (cert_usage) {
243
244 case 0:
245 return "CA constraint";
246
247 case 1:
248 return "Service certificate constraint";
249
250 case 2:
251 return "Trust anchor assertion";
252
253 case 3:
254 return "Domain-issued certificate";
255
256 case 4 ... 254:
257 return "Unassigned";
258
259 case 255:
260 return "Private use";
261 }
262
263 return NULL; /* clang cannot count that we covered everything */
264 }
265
266 const char* tlsa_selector_to_string(uint8_t selector) {
267 switch (selector) {
268
269 case 0:
270 return "Full Certificate";
271
272 case 1:
273 return "SubjectPublicKeyInfo";
274
275 case 2 ... 254:
276 return "Unassigned";
277
278 case 255:
279 return "Private use";
280 }
281
282 return NULL;
283 }
284
285 const char* tlsa_matching_type_to_string(uint8_t selector) {
286
287 switch (selector) {
288
289 case 0:
290 return "No hash used";
291
292 case 1:
293 return "SHA-256";
294
295 case 2:
296 return "SHA-512";
297
298 case 3 ... 254:
299 return "Unassigned";
300
301 case 255:
302 return "Private use";
303 }
304
305 return NULL;
306 }