1/*
2 * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: kx_36.c,v 1.47 2009/12/04 22:06:37 tbox Exp $ */
19
20/* Reviewed: Thu Mar 16 17:24:54 PST 2000 by explorer */
21
22/* RFC2230 */
23
24#ifndef RDATA_IN_1_KX_36_C
25#define RDATA_IN_1_KX_36_C
26
27#define RRTYPE_KX_ATTRIBUTES (0)
28
29static inline isc_result_t
30fromtext_in_kx(ARGS_FROMTEXT) {
31	isc_token_t token;
32	dns_name_t name;
33	isc_buffer_t buffer;
34
35	REQUIRE(type == 36);
36	REQUIRE(rdclass == 1);
37
38	UNUSED(type);
39	UNUSED(rdclass);
40	UNUSED(callbacks);
41
42	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
43				      ISC_FALSE));
44	if (token.value.as_ulong > 0xffffU)
45		RETTOK(ISC_R_RANGE);
46	RETERR(uint16_tobuffer(token.value.as_ulong, target));
47
48	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
49				      ISC_FALSE));
50	dns_name_init(&name, NULL);
51	buffer_fromregion(&buffer, &token.value.as_region);
52	origin = (origin != NULL) ? origin : dns_rootname;
53	RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
54	return (ISC_R_SUCCESS);
55}
56
57static inline isc_result_t
58totext_in_kx(ARGS_TOTEXT) {
59	isc_region_t region;
60	dns_name_t name;
61	dns_name_t prefix;
62	isc_boolean_t sub;
63	char buf[sizeof("64000")];
64	unsigned short num;
65
66	REQUIRE(rdata->type == 36);
67	REQUIRE(rdata->rdclass == 1);
68	REQUIRE(rdata->length != 0);
69
70	dns_name_init(&name, NULL);
71	dns_name_init(&prefix, NULL);
72
73	dns_rdata_toregion(rdata, &region);
74	num = uint16_fromregion(&region);
75	isc_region_consume(&region, 2);
76	sprintf(buf, "%u", num);
77	RETERR(str_totext(buf, target));
78
79	RETERR(str_totext(" ", target));
80
81	dns_name_fromregion(&name, &region);
82	sub = name_prefix(&name, tctx->origin, &prefix);
83	return (dns_name_totext(&prefix, sub, target));
84}
85
86static inline isc_result_t
87fromwire_in_kx(ARGS_FROMWIRE) {
88	dns_name_t name;
89	isc_region_t sregion;
90
91	REQUIRE(type == 36);
92	REQUIRE(rdclass == 1);
93
94	UNUSED(type);
95	UNUSED(rdclass);
96
97	dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
98
99	dns_name_init(&name, NULL);
100
101	isc_buffer_activeregion(source, &sregion);
102	if (sregion.length < 2)
103		return (ISC_R_UNEXPECTEDEND);
104	RETERR(mem_tobuffer(target, sregion.base, 2));
105	isc_buffer_forward(source, 2);
106	return (dns_name_fromwire(&name, source, dctx, options, target));
107}
108
109static inline isc_result_t
110towire_in_kx(ARGS_TOWIRE) {
111	dns_name_t name;
112	dns_offsets_t offsets;
113	isc_region_t region;
114
115	REQUIRE(rdata->type == 36);
116	REQUIRE(rdata->rdclass == 1);
117	REQUIRE(rdata->length != 0);
118
119	dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
120	dns_rdata_toregion(rdata, &region);
121	RETERR(mem_tobuffer(target, region.base, 2));
122	isc_region_consume(&region, 2);
123
124	dns_name_init(&name, offsets);
125	dns_name_fromregion(&name, &region);
126
127	return (dns_name_towire(&name, cctx, target));
128}
129
130static inline int
131compare_in_kx(ARGS_COMPARE) {
132	dns_name_t name1;
133	dns_name_t name2;
134	isc_region_t region1;
135	isc_region_t region2;
136	int order;
137
138	REQUIRE(rdata1->type == rdata2->type);
139	REQUIRE(rdata1->rdclass == rdata2->rdclass);
140	REQUIRE(rdata1->type == 36);
141	REQUIRE(rdata1->rdclass == 1);
142	REQUIRE(rdata1->length != 0);
143	REQUIRE(rdata2->length != 0);
144
145	order = memcmp(rdata1->data, rdata2->data, 2);
146	if (order != 0)
147		return (order < 0 ? -1 : 1);
148
149	dns_name_init(&name1, NULL);
150	dns_name_init(&name2, NULL);
151
152	dns_rdata_toregion(rdata1, &region1);
153	dns_rdata_toregion(rdata2, &region2);
154
155	isc_region_consume(&region1, 2);
156	isc_region_consume(&region2, 2);
157
158	dns_name_fromregion(&name1, &region1);
159	dns_name_fromregion(&name2, &region2);
160
161	return (dns_name_rdatacompare(&name1, &name2));
162}
163
164static inline isc_result_t
165fromstruct_in_kx(ARGS_FROMSTRUCT) {
166	dns_rdata_in_kx_t *kx = source;
167	isc_region_t region;
168
169	REQUIRE(type == 36);
170	REQUIRE(rdclass == 1);
171	REQUIRE(source != NULL);
172	REQUIRE(kx->common.rdtype == type);
173	REQUIRE(kx->common.rdclass == rdclass);
174
175	UNUSED(type);
176	UNUSED(rdclass);
177
178	RETERR(uint16_tobuffer(kx->preference, target));
179	dns_name_toregion(&kx->exchange, &region);
180	return (isc_buffer_copyregion(target, &region));
181}
182
183static inline isc_result_t
184tostruct_in_kx(ARGS_TOSTRUCT) {
185	isc_region_t region;
186	dns_rdata_in_kx_t *kx = target;
187	dns_name_t name;
188
189	REQUIRE(rdata->type == 36);
190	REQUIRE(rdata->rdclass == 1);
191	REQUIRE(target != NULL);
192	REQUIRE(rdata->length != 0);
193
194	kx->common.rdclass = rdata->rdclass;
195	kx->common.rdtype = rdata->type;
196	ISC_LINK_INIT(&kx->common, link);
197
198	dns_name_init(&name, NULL);
199	dns_rdata_toregion(rdata, &region);
200
201	kx->preference = uint16_fromregion(&region);
202	isc_region_consume(&region, 2);
203
204	dns_name_fromregion(&name, &region);
205	dns_name_init(&kx->exchange, NULL);
206	RETERR(name_duporclone(&name, mctx, &kx->exchange));
207	kx->mctx = mctx;
208	return (ISC_R_SUCCESS);
209}
210
211static inline void
212freestruct_in_kx(ARGS_FREESTRUCT) {
213	dns_rdata_in_kx_t *kx = source;
214
215	REQUIRE(source != NULL);
216	REQUIRE(kx->common.rdclass == 1);
217	REQUIRE(kx->common.rdtype == 36);
218
219	if (kx->mctx == NULL)
220		return;
221
222	dns_name_free(&kx->exchange, kx->mctx);
223	kx->mctx = NULL;
224}
225
226static inline isc_result_t
227additionaldata_in_kx(ARGS_ADDLDATA) {
228	dns_name_t name;
229	dns_offsets_t offsets;
230	isc_region_t region;
231
232	REQUIRE(rdata->type == 36);
233	REQUIRE(rdata->rdclass == 1);
234
235	dns_name_init(&name, offsets);
236	dns_rdata_toregion(rdata, &region);
237	isc_region_consume(&region, 2);
238	dns_name_fromregion(&name, &region);
239
240	return ((add)(arg, &name, dns_rdatatype_a));
241}
242
243static inline isc_result_t
244digest_in_kx(ARGS_DIGEST) {
245	isc_region_t r1, r2;
246	dns_name_t name;
247
248	REQUIRE(rdata->type == 36);
249	REQUIRE(rdata->rdclass == 1);
250
251	dns_rdata_toregion(rdata, &r1);
252	r2 = r1;
253	isc_region_consume(&r2, 2);
254	r1.length = 2;
255	RETERR((digest)(arg, &r1));
256	dns_name_init(&name, NULL);
257	dns_name_fromregion(&name, &r2);
258	return (dns_name_digest(&name, digest, arg));
259}
260
261static inline isc_boolean_t
262checkowner_in_kx(ARGS_CHECKOWNER) {
263
264	REQUIRE(type == 36);
265	REQUIRE(rdclass == 1);
266
267	UNUSED(name);
268	UNUSED(type);
269	UNUSED(rdclass);
270	UNUSED(wildcard);
271
272	return (ISC_TRUE);
273}
274
275static inline isc_boolean_t
276checknames_in_kx(ARGS_CHECKNAMES) {
277
278	REQUIRE(rdata->type == 36);
279	REQUIRE(rdata->rdclass == 1);
280
281	UNUSED(rdata);
282	UNUSED(owner);
283	UNUSED(bad);
284
285	return (ISC_TRUE);
286}
287
288static inline int
289casecompare_in_kx(ARGS_COMPARE) {
290	return (compare_in_kx(rdata1, rdata2));
291}
292
293#endif	/* RDATA_IN_1_KX_36_C */
294