1 /*
2 * Copyright (C) 2005, 2007, 2009, 2011, 2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /* $Id$ */
18
19 #ifndef RDATA_GENERIC_IPSECKEY_45_C
20 #define RDATA_GENERIC_IPSECKEY_45_C
21
22 #include <string.h>
23
24 #include <isc/net.h>
25
26 #define RRTYPE_IPSECKEY_ATTRIBUTES (0)
27
28 static inline isc_result_t
fromtext_ipseckey(ARGS_FROMTEXT)29 fromtext_ipseckey(ARGS_FROMTEXT) {
30 isc_token_t token;
31 dns_name_t name;
32 isc_buffer_t buffer;
33 unsigned int gateway;
34 struct in_addr addr;
35 unsigned char addr6[16];
36 isc_region_t region;
37
38 REQUIRE(type == dns_rdatatype_ipseckey);
39
40 UNUSED(type);
41 UNUSED(rdclass);
42 UNUSED(callbacks);
43
44 /*
45 * Precedence.
46 */
47 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
48 ISC_FALSE));
49 if (token.value.as_ulong > 0xffU)
50 RETTOK(ISC_R_RANGE);
51 RETERR(uint8_tobuffer(token.value.as_ulong, target));
52
53 /*
54 * Gateway type.
55 */
56 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
57 ISC_FALSE));
58 if (token.value.as_ulong > 0x3U)
59 RETTOK(ISC_R_RANGE);
60 RETERR(uint8_tobuffer(token.value.as_ulong, target));
61 gateway = token.value.as_ulong;
62
63 /*
64 * Algorithm.
65 */
66 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
67 ISC_FALSE));
68 if (token.value.as_ulong > 0xffU)
69 RETTOK(ISC_R_RANGE);
70 RETERR(uint8_tobuffer(token.value.as_ulong, target));
71
72 /*
73 * Gateway.
74 */
75 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
76 ISC_FALSE));
77
78 switch (gateway) {
79 case 0:
80 if (strcmp(DNS_AS_STR(token), ".") != 0)
81 RETTOK(DNS_R_SYNTAX);
82 break;
83
84 case 1:
85 if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1)
86 RETTOK(DNS_R_BADDOTTEDQUAD);
87 isc_buffer_availableregion(target, ®ion);
88 if (region.length < 4)
89 return (ISC_R_NOSPACE);
90 memmove(region.base, &addr, 4);
91 isc_buffer_add(target, 4);
92 break;
93
94 case 2:
95 if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1)
96 RETTOK(DNS_R_BADAAAA);
97 isc_buffer_availableregion(target, ®ion);
98 if (region.length < 16)
99 return (ISC_R_NOSPACE);
100 memmove(region.base, addr6, 16);
101 isc_buffer_add(target, 16);
102 break;
103
104 case 3:
105 dns_name_init(&name, NULL);
106 buffer_fromregion(&buffer, &token.value.as_region);
107 if (origin == NULL)
108 origin = dns_rootname;
109 RETTOK(dns_name_fromtext(&name, &buffer, origin,
110 options, target));
111 break;
112 }
113
114 /*
115 * Public key.
116 */
117 return (isc_base64_tobuffer(lexer, target, -1));
118 }
119
120 static inline isc_result_t
totext_ipseckey(ARGS_TOTEXT)121 totext_ipseckey(ARGS_TOTEXT) {
122 isc_region_t region;
123 dns_name_t name;
124 char buf[sizeof("255 ")];
125 unsigned short num;
126 unsigned short gateway;
127
128 REQUIRE(rdata->type == dns_rdatatype_ipseckey);
129 REQUIRE(rdata->length >= 3);
130
131 dns_name_init(&name, NULL);
132
133 if (rdata->data[1] > 3U)
134 return (ISC_R_NOTIMPLEMENTED);
135
136 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
137 RETERR(str_totext("( ", target));
138
139 /*
140 * Precedence.
141 */
142 dns_rdata_toregion(rdata, ®ion);
143 num = uint8_fromregion(®ion);
144 isc_region_consume(®ion, 1);
145 sprintf(buf, "%u ", num);
146 RETERR(str_totext(buf, target));
147
148 /*
149 * Gateway type.
150 */
151 gateway = uint8_fromregion(®ion);
152 isc_region_consume(®ion, 1);
153 sprintf(buf, "%u ", gateway);
154 RETERR(str_totext(buf, target));
155
156 /*
157 * Algorithm.
158 */
159 num = uint8_fromregion(®ion);
160 isc_region_consume(®ion, 1);
161 sprintf(buf, "%u ", num);
162 RETERR(str_totext(buf, target));
163
164 /*
165 * Gateway.
166 */
167 switch (gateway) {
168 case 0:
169 RETERR(str_totext(".", target));
170 break;
171
172 case 1:
173 RETERR(inet_totext(AF_INET, ®ion, target));
174 isc_region_consume(®ion, 4);
175 break;
176
177 case 2:
178 RETERR(inet_totext(AF_INET6, ®ion, target));
179 isc_region_consume(®ion, 16);
180 break;
181
182 case 3:
183 dns_name_fromregion(&name, ®ion);
184 RETERR(dns_name_totext(&name, ISC_FALSE, target));
185 isc_region_consume(®ion, name_length(&name));
186 break;
187 }
188
189 /*
190 * Key.
191 */
192 if (region.length > 0U) {
193 RETERR(str_totext(tctx->linebreak, target));
194 if (tctx->width == 0) /* No splitting */
195 RETERR(isc_base64_totext(®ion, 60, "", target));
196 else
197 RETERR(isc_base64_totext(®ion, tctx->width - 2,
198 tctx->linebreak, target));
199 }
200
201 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
202 RETERR(str_totext(" )", target));
203 return (ISC_R_SUCCESS);
204 }
205
206 static inline isc_result_t
fromwire_ipseckey(ARGS_FROMWIRE)207 fromwire_ipseckey(ARGS_FROMWIRE) {
208 dns_name_t name;
209 isc_region_t region;
210
211 REQUIRE(type == dns_rdatatype_ipseckey);
212
213 UNUSED(type);
214 UNUSED(rdclass);
215
216 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
217
218 dns_name_init(&name, NULL);
219
220 isc_buffer_activeregion(source, ®ion);
221 if (region.length < 3)
222 return (ISC_R_UNEXPECTEDEND);
223
224 switch (region.base[1]) {
225 case 0:
226 isc_buffer_forward(source, region.length);
227 return (mem_tobuffer(target, region.base, region.length));
228
229 case 1:
230 if (region.length < 7)
231 return (ISC_R_UNEXPECTEDEND);
232 isc_buffer_forward(source, region.length);
233 return (mem_tobuffer(target, region.base, region.length));
234
235 case 2:
236 if (region.length < 19)
237 return (ISC_R_UNEXPECTEDEND);
238 isc_buffer_forward(source, region.length);
239 return (mem_tobuffer(target, region.base, region.length));
240
241 case 3:
242 RETERR(mem_tobuffer(target, region.base, 3));
243 isc_buffer_forward(source, 3);
244 RETERR(dns_name_fromwire(&name, source, dctx, options, target));
245 isc_buffer_activeregion(source, ®ion);
246 isc_buffer_forward(source, region.length);
247 return(mem_tobuffer(target, region.base, region.length));
248
249 default:
250 return (ISC_R_NOTIMPLEMENTED);
251 }
252 }
253
254 static inline isc_result_t
towire_ipseckey(ARGS_TOWIRE)255 towire_ipseckey(ARGS_TOWIRE) {
256 isc_region_t region;
257
258 REQUIRE(rdata->type == dns_rdatatype_ipseckey);
259 REQUIRE(rdata->length != 0);
260
261 UNUSED(cctx);
262
263 dns_rdata_toregion(rdata, ®ion);
264 return (mem_tobuffer(target, region.base, region.length));
265 }
266
267 static inline int
compare_ipseckey(ARGS_COMPARE)268 compare_ipseckey(ARGS_COMPARE) {
269 isc_region_t region1;
270 isc_region_t region2;
271
272 REQUIRE(rdata1->type == rdata2->type);
273 REQUIRE(rdata1->rdclass == rdata2->rdclass);
274 REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
275 REQUIRE(rdata1->length >= 3);
276 REQUIRE(rdata2->length >= 3);
277
278 dns_rdata_toregion(rdata1, ®ion1);
279 dns_rdata_toregion(rdata2, ®ion2);
280
281 return (isc_region_compare(®ion1, ®ion2));
282 }
283
284 static inline isc_result_t
fromstruct_ipseckey(ARGS_FROMSTRUCT)285 fromstruct_ipseckey(ARGS_FROMSTRUCT) {
286 dns_rdata_ipseckey_t *ipseckey = source;
287 isc_region_t region;
288 isc_uint32_t n;
289
290 REQUIRE(type == dns_rdatatype_ipseckey);
291 REQUIRE(source != NULL);
292 REQUIRE(ipseckey->common.rdtype == type);
293 REQUIRE(ipseckey->common.rdclass == rdclass);
294
295 UNUSED(type);
296 UNUSED(rdclass);
297
298 if (ipseckey->gateway_type > 3U)
299 return (ISC_R_NOTIMPLEMENTED);
300
301 RETERR(uint8_tobuffer(ipseckey->precedence, target));
302 RETERR(uint8_tobuffer(ipseckey->gateway_type, target));
303 RETERR(uint8_tobuffer(ipseckey->algorithm, target));
304
305 switch (ipseckey->gateway_type) {
306 case 0:
307 break;
308
309 case 1:
310 n = ntohl(ipseckey->in_addr.s_addr);
311 RETERR(uint32_tobuffer(n, target));
312 break;
313
314 case 2:
315 RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16));
316 break;
317
318 case 3:
319 dns_name_toregion(&ipseckey->gateway, ®ion);
320 RETERR(isc_buffer_copyregion(target, ®ion));
321 break;
322 }
323
324 return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength));
325 }
326
327 static inline isc_result_t
tostruct_ipseckey(ARGS_TOSTRUCT)328 tostruct_ipseckey(ARGS_TOSTRUCT) {
329 isc_region_t region;
330 dns_rdata_ipseckey_t *ipseckey = target;
331 dns_name_t name;
332 isc_uint32_t n;
333
334 REQUIRE(rdata->type == dns_rdatatype_ipseckey);
335 REQUIRE(target != NULL);
336 REQUIRE(rdata->length >= 3);
337
338 if (rdata->data[1] > 3U)
339 return (ISC_R_NOTIMPLEMENTED);
340
341 ipseckey->common.rdclass = rdata->rdclass;
342 ipseckey->common.rdtype = rdata->type;
343 ISC_LINK_INIT(&ipseckey->common, link);
344
345 dns_name_init(&name, NULL);
346 dns_rdata_toregion(rdata, ®ion);
347
348 ipseckey->precedence = uint8_fromregion(®ion);
349 isc_region_consume(®ion, 1);
350
351 ipseckey->gateway_type = uint8_fromregion(®ion);
352 isc_region_consume(®ion, 1);
353
354 ipseckey->algorithm = uint8_fromregion(®ion);
355 isc_region_consume(®ion, 1);
356
357 switch (ipseckey->gateway_type) {
358 case 0:
359 break;
360
361 case 1:
362 n = uint32_fromregion(®ion);
363 ipseckey->in_addr.s_addr = htonl(n);
364 isc_region_consume(®ion, 4);
365 break;
366
367 case 2:
368 memmove(ipseckey->in6_addr.s6_addr, region.base, 16);
369 isc_region_consume(®ion, 16);
370 break;
371
372 case 3:
373 dns_name_init(&ipseckey->gateway, NULL);
374 dns_name_fromregion(&name, ®ion);
375 RETERR(name_duporclone(&name, mctx, &ipseckey->gateway));
376 isc_region_consume(®ion, name_length(&name));
377 break;
378 }
379
380 ipseckey->keylength = region.length;
381 if (ipseckey->keylength != 0U) {
382 ipseckey->key = mem_maybedup(mctx, region.base,
383 ipseckey->keylength);
384 if (ipseckey->key == NULL) {
385 if (ipseckey->gateway_type == 3)
386 dns_name_free(&ipseckey->gateway,
387 ipseckey->mctx);
388 return (ISC_R_NOMEMORY);
389 }
390 } else
391 ipseckey->key = NULL;
392
393 ipseckey->mctx = mctx;
394 return (ISC_R_SUCCESS);
395 }
396
397 static inline void
freestruct_ipseckey(ARGS_FREESTRUCT)398 freestruct_ipseckey(ARGS_FREESTRUCT) {
399 dns_rdata_ipseckey_t *ipseckey = source;
400
401 REQUIRE(source != NULL);
402 REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey);
403
404 if (ipseckey->mctx == NULL)
405 return;
406
407 if (ipseckey->gateway_type == 3)
408 dns_name_free(&ipseckey->gateway, ipseckey->mctx);
409
410 if (ipseckey->key != NULL)
411 isc_mem_free(ipseckey->mctx, ipseckey->key);
412
413 ipseckey->mctx = NULL;
414 }
415
416 static inline isc_result_t
additionaldata_ipseckey(ARGS_ADDLDATA)417 additionaldata_ipseckey(ARGS_ADDLDATA) {
418
419 REQUIRE(rdata->type == dns_rdatatype_ipseckey);
420
421 UNUSED(rdata);
422 UNUSED(add);
423 UNUSED(arg);
424
425 return (ISC_R_SUCCESS);
426 }
427
428 static inline isc_result_t
digest_ipseckey(ARGS_DIGEST)429 digest_ipseckey(ARGS_DIGEST) {
430 isc_region_t region;
431
432 REQUIRE(rdata->type == dns_rdatatype_ipseckey);
433
434 dns_rdata_toregion(rdata, ®ion);
435 return ((digest)(arg, ®ion));
436 }
437
438 static inline isc_boolean_t
checkowner_ipseckey(ARGS_CHECKOWNER)439 checkowner_ipseckey(ARGS_CHECKOWNER) {
440
441 REQUIRE(type == dns_rdatatype_ipseckey);
442
443 UNUSED(name);
444 UNUSED(type);
445 UNUSED(rdclass);
446 UNUSED(wildcard);
447
448 return (ISC_TRUE);
449 }
450
451 static inline isc_boolean_t
checknames_ipseckey(ARGS_CHECKNAMES)452 checknames_ipseckey(ARGS_CHECKNAMES) {
453
454 REQUIRE(rdata->type == dns_rdatatype_ipseckey);
455
456 UNUSED(rdata);
457 UNUSED(owner);
458 UNUSED(bad);
459
460 return (ISC_TRUE);
461 }
462
463 static inline int
casecompare_ipseckey(ARGS_COMPARE)464 casecompare_ipseckey(ARGS_COMPARE) {
465 isc_region_t region1;
466 isc_region_t region2;
467 dns_name_t name1;
468 dns_name_t name2;
469 int order;
470
471 REQUIRE(rdata1->type == rdata2->type);
472 REQUIRE(rdata1->rdclass == rdata2->rdclass);
473 REQUIRE(rdata1->type == dns_rdatatype_ipseckey);
474 REQUIRE(rdata1->length >= 3);
475 REQUIRE(rdata2->length >= 3);
476
477 dns_rdata_toregion(rdata1, ®ion1);
478 dns_rdata_toregion(rdata2, ®ion2);
479
480 if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3)
481 return (isc_region_compare(®ion1, ®ion2));
482
483 dns_name_init(&name1, NULL);
484 dns_name_init(&name2, NULL);
485
486 isc_region_consume(®ion1, 3);
487 isc_region_consume(®ion2, 3);
488
489 dns_name_fromregion(&name1, ®ion1);
490 dns_name_fromregion(&name2, ®ion2);
491
492 order = dns_name_rdatacompare(&name1, &name2);
493 if (order != 0)
494 return (order);
495
496 isc_region_consume(®ion1, name_length(&name1));
497 isc_region_consume(®ion2, name_length(&name2));
498
499 return (isc_region_compare(®ion1, ®ion2));
500 }
501
502 #endif /* RDATA_GENERIC_IPSECKEY_45_C */
503