Merge branch 'vendor/FILE'
[dragonfly.git] / contrib / bind / lib / dns / rdata / generic / ipseckey_45.c
1 /*
2  * Copyright (C) 2005, 2007, 2009  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: ipseckey_45.c,v 1.4.128.3 2009/09/18 21:56:25 jinmei Exp $ */
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
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 == 45);
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, &region);
88                 if (region.length < 4)
89                         return (ISC_R_NOSPACE);
90                 memcpy(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, &region);
98                 if (region.length < 16)
99                         return (ISC_R_NOSPACE);
100                 memcpy(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                 origin = (origin != NULL) ? origin : dns_rootname;
108                 RETTOK(dns_name_fromtext(&name, &buffer, origin,
109                                          options, target));
110                 break;
111         }
112
113         /*
114          * Public key.
115          */
116         return (isc_base64_tobuffer(lexer, target, -1));
117 }
118
119 static inline isc_result_t
120 totext_ipseckey(ARGS_TOTEXT) {
121         isc_region_t region;
122         dns_name_t name;
123         dns_name_t prefix;
124         isc_boolean_t sub;
125         char buf[sizeof("255 ")];
126         unsigned short num;
127         unsigned short gateway;
128
129         REQUIRE(rdata->type == 45);
130         REQUIRE(rdata->length >= 3);
131
132         dns_name_init(&name, NULL);
133         dns_name_init(&prefix, NULL);
134
135         if (rdata->data[1] > 3U)
136                 return (ISC_R_NOTIMPLEMENTED);
137
138         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
139                 RETERR(str_totext("( ", target));
140
141         /*
142          * Precedence.
143          */
144         dns_rdata_toregion(rdata, &region);
145         num = uint8_fromregion(&region);
146         isc_region_consume(&region, 1);
147         sprintf(buf, "%u ", num);
148         RETERR(str_totext(buf, target));
149
150         /*
151          * Gateway type.
152          */
153         gateway = uint8_fromregion(&region);
154         isc_region_consume(&region, 1);
155         sprintf(buf, "%u ", gateway);
156         RETERR(str_totext(buf, target));
157
158         /*
159          * Algorithm.
160          */
161         num = uint8_fromregion(&region);
162         isc_region_consume(&region, 1);
163         sprintf(buf, "%u ", num);
164         RETERR(str_totext(buf, target));
165
166         /*
167          * Gateway.
168          */
169         switch (gateway) {
170         case 0:
171                 RETERR(str_totext(".", target));
172                 break;
173
174         case 1:
175                 RETERR(inet_totext(AF_INET, &region, target));
176                 isc_region_consume(&region, 4);
177                 break;
178
179         case 2:
180                 RETERR(inet_totext(AF_INET6, &region, target));
181                 isc_region_consume(&region, 16);
182                 break;
183
184         case 3:
185                 dns_name_fromregion(&name, &region);
186                 sub = name_prefix(&name, tctx->origin, &prefix);
187                 RETERR(dns_name_totext(&prefix, sub, target));
188                 isc_region_consume(&region, name_length(&name));
189                 break;
190         }
191
192         /*
193          * Key.
194          */
195         if (region.length > 0U) {
196                 RETERR(str_totext(tctx->linebreak, target));
197                 RETERR(isc_base64_totext(&region, 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
207 fromwire_ipseckey(ARGS_FROMWIRE) {
208         dns_name_t name;
209         isc_region_t region;
210
211         REQUIRE(type == 45);
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, &region);
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, &region);
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
255 towire_ipseckey(ARGS_TOWIRE) {
256         isc_region_t region;
257
258         REQUIRE(rdata->type == 45);
259         REQUIRE(rdata->length != 0);
260
261         UNUSED(cctx);
262
263         dns_rdata_toregion(rdata, &region);
264         return (mem_tobuffer(target, region.base, region.length));
265 }
266
267 static inline int
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 == 45);
275         REQUIRE(rdata1->length >= 3);
276         REQUIRE(rdata2->length >= 3);
277
278         dns_rdata_toregion(rdata1, &region1);
279         dns_rdata_toregion(rdata2, &region2);
280
281         return (isc_region_compare(&region1, &region2));
282 }
283
284 static inline isc_result_t
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 == 45);
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, &region);
320                 RETERR(isc_buffer_copyregion(target, &region));
321                 break;
322         }
323
324         return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength));
325 }
326
327 static inline isc_result_t
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 == 45);
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, &region);
347
348         ipseckey->precedence = uint8_fromregion(&region);
349         isc_region_consume(&region, 1);
350
351         ipseckey->gateway_type = uint8_fromregion(&region);
352         isc_region_consume(&region, 1);
353
354         ipseckey->algorithm = uint8_fromregion(&region);
355         isc_region_consume(&region, 1);
356
357         switch (ipseckey->gateway_type) {
358         case 0:
359                 break;
360
361         case 1:
362                 n = uint32_fromregion(&region);
363                 ipseckey->in_addr.s_addr = htonl(n);
364                 isc_region_consume(&region, 4);
365                 break;
366
367         case 2:
368                 memcpy(ipseckey->in6_addr.s6_addr, region.base, 16);
369                 isc_region_consume(&region, 16);
370                 break;
371
372         case 3:
373                 dns_name_init(&ipseckey->gateway, NULL);
374                 dns_name_fromregion(&name, &region);
375                 RETERR(name_duporclone(&name, mctx, &ipseckey->gateway));
376                 isc_region_consume(&region, 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
398 freestruct_ipseckey(ARGS_FREESTRUCT) {
399         dns_rdata_ipseckey_t *ipseckey = source;
400
401         REQUIRE(source != NULL);
402         REQUIRE(ipseckey->common.rdtype == 45);
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
417 additionaldata_ipseckey(ARGS_ADDLDATA) {
418
419         REQUIRE(rdata->type == 45);
420
421         UNUSED(rdata);
422         UNUSED(add);
423         UNUSED(arg);
424
425         return (ISC_R_SUCCESS);
426 }
427
428 static inline isc_result_t
429 digest_ipseckey(ARGS_DIGEST) {
430         isc_region_t region;
431
432         REQUIRE(rdata->type == 45);
433
434         dns_rdata_toregion(rdata, &region);
435         return ((digest)(arg, &region));
436 }
437
438 static inline isc_boolean_t
439 checkowner_ipseckey(ARGS_CHECKOWNER) {
440
441         REQUIRE(type == 45);
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
452 checknames_ipseckey(ARGS_CHECKNAMES) {
453
454         REQUIRE(rdata->type == 45);
455
456         UNUSED(rdata);
457         UNUSED(owner);
458         UNUSED(bad);
459
460         return (ISC_TRUE);
461 }
462
463 #endif  /* RDATA_GENERIC_IPSECKEY_45_C */