Merge branch 'vendor/MPC'
[dragonfly.git] / contrib / ldns / rr_functions.c
1 /*
2  * rr_function.c
3  *
4  * function that operate on specific rr types
5  *
6  * (c) NLnet Labs, 2004-2006
7  * See the file LICENSE for the license
8  */
9
10 /*
11  * These come strait from perldoc Net::DNS::RR::xxx
12  * first the read variant, then the write. This is
13  * not complete.
14  */
15
16 #include <ldns/config.h>
17
18 #include <ldns/ldns.h>
19
20 #include <limits.h>
21 #include <strings.h>
22
23 /**
24  * return a specific rdf
25  * \param[in] type type of RR
26  * \param[in] rr   the rr itself
27  * \param[in] pos  at which postion to get it
28  * \return the rdf sought
29  */
30 static ldns_rdf *
31 ldns_rr_function(ldns_rr_type type, const ldns_rr *rr, size_t pos)
32 {
33         if (!rr || ldns_rr_get_type(rr) != type) {
34                 return NULL;
35         }
36         return ldns_rr_rdf(rr, pos);
37 }
38
39 /**
40  * set a specific rdf
41  * \param[in] type type of RR
42  * \param[in] rr   the rr itself
43  * \param[in] rdf  the rdf to set
44  * \param[in] pos  at which postion to set it
45  * \return true or false
46  */
47 static bool
48 ldns_rr_set_function(ldns_rr_type type, ldns_rr *rr, ldns_rdf *rdf, size_t pos)
49 {
50         ldns_rdf *pop;
51         if (!rr || ldns_rr_get_type(rr) != type) {
52                 return false;
53         }
54         pop = ldns_rr_set_rdf(rr, rdf, pos);
55         ldns_rdf_deep_free(pop);
56         return true;
57 }
58
59 /* A/AAAA records */
60 ldns_rdf *
61 ldns_rr_a_address(const ldns_rr *r)
62 {
63         /* 2 types to check, cannot use the macro */
64         if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
65                         ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
66                 return NULL;
67         }
68         return ldns_rr_rdf(r, 0);
69 }
70
71 bool
72 ldns_rr_a_set_address(ldns_rr *r, ldns_rdf *f)
73 {
74         /* 2 types to check, cannot use the macro... */
75         ldns_rdf *pop;
76         if (!r || (ldns_rr_get_type(r) != LDNS_RR_TYPE_A &&
77                         ldns_rr_get_type(r) != LDNS_RR_TYPE_AAAA)) {
78                 return false;
79         }
80         pop = ldns_rr_set_rdf(r, f, 0);
81         if (pop) {
82                 LDNS_FREE(pop);
83                 return true;
84         } else {
85                 return false;
86         }
87 }
88
89 /* NS record */
90 ldns_rdf *
91 ldns_rr_ns_nsdname(const ldns_rr *r)
92 {
93         return ldns_rr_function(LDNS_RR_TYPE_NS, r, 0);
94 }
95
96 /* MX record */
97 ldns_rdf *
98 ldns_rr_mx_preference(const ldns_rr *r)
99 {
100         return ldns_rr_function(LDNS_RR_TYPE_MX, r, 0);
101 }
102
103 ldns_rdf *
104 ldns_rr_mx_exchange(const ldns_rr *r)
105 {
106         return ldns_rr_function(LDNS_RR_TYPE_MX, r, 1);
107 }
108
109 /* RRSIG record */
110 ldns_rdf *
111 ldns_rr_rrsig_typecovered(const ldns_rr *r)
112 {
113         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 0);
114 }
115
116 bool
117 ldns_rr_rrsig_set_typecovered(ldns_rr *r, ldns_rdf *f)
118 {
119         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 0);
120 }
121
122 ldns_rdf *
123 ldns_rr_rrsig_algorithm(const ldns_rr *r)
124 {
125         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 1);
126 }
127
128 bool
129 ldns_rr_rrsig_set_algorithm(ldns_rr *r, ldns_rdf *f)
130 {
131         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 1);
132 }
133
134 ldns_rdf *
135 ldns_rr_rrsig_labels(const ldns_rr *r)
136 {
137         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 2);
138 }
139
140 bool
141 ldns_rr_rrsig_set_labels(ldns_rr *r, ldns_rdf *f)
142 {
143         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 2);
144 }
145
146 ldns_rdf *
147 ldns_rr_rrsig_origttl(const ldns_rr *r)
148 {
149         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 3);
150 }
151
152 bool
153 ldns_rr_rrsig_set_origttl(ldns_rr *r, ldns_rdf *f)
154 {
155         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 3);
156 }
157
158 ldns_rdf *
159 ldns_rr_rrsig_expiration(const ldns_rr *r)
160 {
161         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 4);
162 }
163
164 bool
165 ldns_rr_rrsig_set_expiration(ldns_rr *r, ldns_rdf *f)
166 {
167         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 4);
168 }
169
170 ldns_rdf *
171 ldns_rr_rrsig_inception(const ldns_rr *r)
172 {
173         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 5);
174 }
175
176 bool
177 ldns_rr_rrsig_set_inception(ldns_rr *r, ldns_rdf *f)
178 {
179         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 5);
180 }
181
182 ldns_rdf *
183 ldns_rr_rrsig_keytag(const ldns_rr *r)
184 {
185         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 6);
186 }
187
188 bool
189 ldns_rr_rrsig_set_keytag(ldns_rr *r, ldns_rdf *f)
190 {
191         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 6);
192 }
193
194 ldns_rdf *
195 ldns_rr_rrsig_signame(const ldns_rr *r)
196 {
197         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 7);
198 }
199
200 bool
201 ldns_rr_rrsig_set_signame(ldns_rr *r, ldns_rdf *f)
202 {
203         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 7);
204 }
205
206 ldns_rdf *
207 ldns_rr_rrsig_sig(const ldns_rr *r)
208 {
209         return ldns_rr_function(LDNS_RR_TYPE_RRSIG, r, 8);
210 }
211
212 bool
213 ldns_rr_rrsig_set_sig(ldns_rr *r, ldns_rdf *f)
214 {
215         return ldns_rr_set_function(LDNS_RR_TYPE_RRSIG, r, f, 8);
216 }
217
218 /* DNSKEY record */
219 ldns_rdf *
220 ldns_rr_dnskey_flags(const ldns_rr *r)
221 {
222         return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 0);
223 }
224
225 bool
226 ldns_rr_dnskey_set_flags(ldns_rr *r, ldns_rdf *f)
227 {
228         return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 0);
229 }
230
231 ldns_rdf *
232 ldns_rr_dnskey_protocol(const ldns_rr *r)
233 {
234         return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 1);
235 }
236
237 bool
238 ldns_rr_dnskey_set_protocol(ldns_rr *r, ldns_rdf *f)
239 {
240         return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 1);
241 }
242
243 ldns_rdf *
244 ldns_rr_dnskey_algorithm(const ldns_rr *r)
245 {
246         return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 2);
247 }
248
249 bool
250 ldns_rr_dnskey_set_algorithm(ldns_rr *r, ldns_rdf *f)
251 {
252         return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 2);
253 }
254
255 ldns_rdf *
256 ldns_rr_dnskey_key(const ldns_rr *r)
257 {
258         return ldns_rr_function(LDNS_RR_TYPE_DNSKEY, r, 3);
259 }
260
261 bool
262 ldns_rr_dnskey_set_key(ldns_rr *r, ldns_rdf *f)
263 {
264         return ldns_rr_set_function(LDNS_RR_TYPE_DNSKEY, r, f, 3);
265 }
266
267 size_t
268 ldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
269                             const size_t len,
270                             const ldns_algorithm alg)
271 {
272         /* for DSA keys */
273         uint8_t t;
274         
275         /* for RSA keys */
276         uint16_t exp;
277         uint16_t int16;
278         
279         switch ((ldns_signing_algorithm)alg) {
280         case LDNS_SIGN_DSA:
281         case LDNS_SIGN_DSA_NSEC3:
282                 if (len > 0) {
283                         t = keydata[0];
284                         return (64 + t*8)*8;
285                 } else {
286                         return 0;
287                 }
288                 break;
289         case LDNS_SIGN_RSAMD5:
290         case LDNS_SIGN_RSASHA1:
291         case LDNS_SIGN_RSASHA1_NSEC3:
292 #ifdef USE_SHA2
293         case LDNS_SIGN_RSASHA256:
294         case LDNS_SIGN_RSASHA512:
295 #endif
296                 if (len > 0) {
297                         if (keydata[0] == 0) {
298                                 /* big exponent */
299                                 if (len > 3) {
300                                         memmove(&int16, keydata + 1, 2);
301                                         exp = ntohs(int16);
302                                         return (len - exp - 3)*8;
303                                 } else {
304                                         return 0;
305                                 }
306                         } else {
307                                 exp = keydata[0];
308                                 return (len-exp-1)*8;
309                         }
310                 } else {
311                         return 0;
312                 }
313                 break;
314 #ifdef USE_GOST
315         case LDNS_SIGN_ECC_GOST:
316                 return 512;
317 #endif
318 #ifdef USE_ECDSA
319         case LDNS_SIGN_ECDSAP256SHA256:
320                 return 256;
321         case LDNS_SIGN_ECDSAP384SHA384:
322                 return 384;
323 #endif
324         case LDNS_SIGN_HMACMD5:
325                 return len;
326         default:
327                 return 0;
328         }
329 }
330
331 size_t 
332 ldns_rr_dnskey_key_size(const ldns_rr *key) 
333 {
334         if (!key || !ldns_rr_dnskey_key(key) 
335                         || !ldns_rr_dnskey_algorithm(key)) {
336                 return 0;
337         }
338         return ldns_rr_dnskey_key_size_raw((unsigned char*)ldns_rdf_data(ldns_rr_dnskey_key(key)),
339                                            ldns_rdf_size(ldns_rr_dnskey_key(key)),
340                                            ldns_rdf2native_int8(ldns_rr_dnskey_algorithm(key))
341                                           );
342 }