1/*
2 * Copyright (C) 2012  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/* draft-ietf-dane-protocol-19.txt */
20
21#ifndef RDATA_GENERIC_TLSA_52_C
22#define RDATA_GENERIC_TLSA_52_C
23
24#define RRTYPE_TLSA_ATTRIBUTES 0
25
26static inline isc_result_t
27fromtext_tlsa(ARGS_FROMTEXT) {
28	isc_token_t token;
29
30	REQUIRE(type == 52);
31
32	UNUSED(type);
33	UNUSED(rdclass);
34	UNUSED(origin);
35	UNUSED(options);
36	UNUSED(callbacks);
37
38	/*
39	 * Certificate Usage.
40	 */
41	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
42				      ISC_FALSE));
43	if (token.value.as_ulong > 0xffU)
44		RETTOK(ISC_R_RANGE);
45	RETERR(uint8_tobuffer(token.value.as_ulong, target));
46
47	/*
48	 * Selector.
49	 */
50	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
51				      ISC_FALSE));
52	if (token.value.as_ulong > 0xffU)
53		RETTOK(ISC_R_RANGE);
54	RETERR(uint8_tobuffer(token.value.as_ulong, target));
55
56	/*
57	 * Matching type.
58	 */
59	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
60				      ISC_FALSE));
61	if (token.value.as_ulong > 0xffU)
62		RETTOK(ISC_R_RANGE);
63	RETERR(uint8_tobuffer(token.value.as_ulong, target));
64
65	/*
66	 * Certificate Association Data.
67	 */
68	return (isc_hex_tobuffer(lexer, target, -1));
69}
70
71static inline isc_result_t
72totext_tlsa(ARGS_TOTEXT) {
73	isc_region_t sr;
74	char buf[sizeof("64000 ")];
75	unsigned int n;
76
77	REQUIRE(rdata->type == 52);
78	REQUIRE(rdata->length != 0);
79
80	UNUSED(tctx);
81
82	dns_rdata_toregion(rdata, &sr);
83
84	/*
85	 * Certificate Usage.
86	 */
87	n = uint8_fromregion(&sr);
88	isc_region_consume(&sr, 1);
89	sprintf(buf, "%u ", n);
90	RETERR(str_totext(buf, target));
91
92	/*
93	 * Selector.
94	 */
95	n = uint8_fromregion(&sr);
96	isc_region_consume(&sr, 1);
97	sprintf(buf, "%u ", n);
98	RETERR(str_totext(buf, target));
99
100	/*
101	 * Matching type.
102	 */
103	n = uint8_fromregion(&sr);
104	isc_region_consume(&sr, 1);
105	sprintf(buf, "%u", n);
106	RETERR(str_totext(buf, target));
107
108	/*
109	 * Certificate Association Data.
110	 */
111	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
112		RETERR(str_totext(" (", target));
113	RETERR(str_totext(tctx->linebreak, target));
114	if (tctx->width == 0) /* No splitting */
115		RETERR(isc_hex_totext(&sr, 0, "", target));
116	else
117		RETERR(isc_hex_totext(&sr, tctx->width - 2,
118				      tctx->linebreak, target));
119	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
120		RETERR(str_totext(" )", target));
121	return (ISC_R_SUCCESS);
122}
123
124static inline isc_result_t
125fromwire_tlsa(ARGS_FROMWIRE) {
126	isc_region_t sr;
127
128	REQUIRE(type == 52);
129
130	UNUSED(type);
131	UNUSED(rdclass);
132	UNUSED(dctx);
133	UNUSED(options);
134
135	isc_buffer_activeregion(source, &sr);
136
137	if (sr.length < 3)
138		return (ISC_R_UNEXPECTEDEND);
139
140	isc_buffer_forward(source, sr.length);
141	return (mem_tobuffer(target, sr.base, sr.length));
142}
143
144static inline isc_result_t
145towire_tlsa(ARGS_TOWIRE) {
146	isc_region_t sr;
147
148	REQUIRE(rdata->type == 52);
149	REQUIRE(rdata->length != 0);
150
151	UNUSED(cctx);
152
153	dns_rdata_toregion(rdata, &sr);
154	return (mem_tobuffer(target, sr.base, sr.length));
155}
156
157static inline int
158compare_tlsa(ARGS_COMPARE) {
159	isc_region_t r1;
160	isc_region_t r2;
161
162	REQUIRE(rdata1->type == rdata2->type);
163	REQUIRE(rdata1->rdclass == rdata2->rdclass);
164	REQUIRE(rdata1->type == 52);
165	REQUIRE(rdata1->length != 0);
166	REQUIRE(rdata2->length != 0);
167
168	dns_rdata_toregion(rdata1, &r1);
169	dns_rdata_toregion(rdata2, &r2);
170	return (isc_region_compare(&r1, &r2));
171}
172
173static inline isc_result_t
174fromstruct_tlsa(ARGS_FROMSTRUCT) {
175	dns_rdata_tlsa_t *tlsa = source;
176
177	REQUIRE(type == 52);
178	REQUIRE(source != NULL);
179	REQUIRE(tlsa->common.rdtype == type);
180	REQUIRE(tlsa->common.rdclass == rdclass);
181
182	UNUSED(type);
183	UNUSED(rdclass);
184
185	RETERR(uint8_tobuffer(tlsa->usage, target));
186	RETERR(uint8_tobuffer(tlsa->selector, target));
187	RETERR(uint8_tobuffer(tlsa->match, target));
188
189	return (mem_tobuffer(target, tlsa->data, tlsa->length));
190}
191
192static inline isc_result_t
193tostruct_tlsa(ARGS_TOSTRUCT) {
194	dns_rdata_tlsa_t *tlsa = target;
195	isc_region_t region;
196
197	REQUIRE(rdata->type == 52);
198	REQUIRE(target != NULL);
199	REQUIRE(rdata->length != 0);
200
201	tlsa->common.rdclass = rdata->rdclass;
202	tlsa->common.rdtype = rdata->type;
203	ISC_LINK_INIT(&tlsa->common, link);
204
205	dns_rdata_toregion(rdata, &region);
206
207	tlsa->usage = uint8_fromregion(&region);
208	isc_region_consume(&region, 1);
209	tlsa->selector = uint8_fromregion(&region);
210	isc_region_consume(&region, 1);
211	tlsa->match = uint8_fromregion(&region);
212	isc_region_consume(&region, 1);
213	tlsa->length = region.length;
214
215	tlsa->data = mem_maybedup(mctx, region.base, region.length);
216	if (tlsa->data == NULL)
217		return (ISC_R_NOMEMORY);
218
219	tlsa->mctx = mctx;
220	return (ISC_R_SUCCESS);
221}
222
223static inline void
224freestruct_tlsa(ARGS_FREESTRUCT) {
225	dns_rdata_tlsa_t *tlsa = source;
226
227	REQUIRE(tlsa != NULL);
228	REQUIRE(tlsa->common.rdtype == 52);
229
230	if (tlsa->mctx == NULL)
231		return;
232
233	if (tlsa->data != NULL)
234		isc_mem_free(tlsa->mctx, tlsa->data);
235	tlsa->mctx = NULL;
236}
237
238static inline isc_result_t
239additionaldata_tlsa(ARGS_ADDLDATA) {
240	REQUIRE(rdata->type == 52);
241
242	UNUSED(rdata);
243	UNUSED(add);
244	UNUSED(arg);
245
246	return (ISC_R_SUCCESS);
247}
248
249static inline isc_result_t
250digest_tlsa(ARGS_DIGEST) {
251	isc_region_t r;
252
253	REQUIRE(rdata->type == 52);
254
255	dns_rdata_toregion(rdata, &r);
256
257	return ((digest)(arg, &r));
258}
259
260static inline isc_boolean_t
261checkowner_tlsa(ARGS_CHECKOWNER) {
262
263	REQUIRE(type == 52);
264
265	UNUSED(name);
266	UNUSED(type);
267	UNUSED(rdclass);
268	UNUSED(wildcard);
269
270	return (ISC_TRUE);
271}
272
273static inline isc_boolean_t
274checknames_tlsa(ARGS_CHECKNAMES) {
275
276	REQUIRE(rdata->type == 52);
277
278	UNUSED(rdata);
279	UNUSED(owner);
280	UNUSED(bad);
281
282	return (ISC_TRUE);
283}
284
285static inline int
286casecompare_tlsa(ARGS_COMPARE) {
287	return (compare_tlsa(rdata1, rdata2));
288}
289
290#endif	/* RDATA_GENERIC_TLSA_52_C */
291