1/*
2 * Copyright (C) 2011, 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#ifndef GENERIC_URI_256_C
20#define GENERIC_URI_256_C 1
21
22#define RRTYPE_URI_ATTRIBUTES (0)
23
24static inline isc_result_t
25fromtext_uri(ARGS_FROMTEXT) {
26	isc_token_t token;
27
28	REQUIRE(type == 256);
29
30	UNUSED(type);
31	UNUSED(rdclass);
32	UNUSED(origin);
33	UNUSED(options);
34	UNUSED(callbacks);
35
36	/*
37	 * Priority
38	 */
39	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
40				      ISC_FALSE));
41	if (token.value.as_ulong > 0xffffU)
42		RETTOK(ISC_R_RANGE);
43	RETERR(uint16_tobuffer(token.value.as_ulong, target));
44
45	/*
46	 * Weight
47	 */
48	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
49				      ISC_FALSE));
50	if (token.value.as_ulong > 0xffffU)
51		RETTOK(ISC_R_RANGE);
52	RETERR(uint16_tobuffer(token.value.as_ulong, target));
53
54	/*
55	 * Target URI
56	 */
57	RETERR(isc_lex_getmastertoken(lexer, &token,
58				      isc_tokentype_qstring, ISC_FALSE));
59	if (token.type != isc_tokentype_qstring)
60		RETTOK(DNS_R_SYNTAX);
61	RETTOK(multitxt_fromtext(&token.value.as_textregion, target));
62	return (ISC_R_SUCCESS);
63}
64
65static inline isc_result_t
66totext_uri(ARGS_TOTEXT) {
67	isc_region_t region;
68	unsigned short priority, weight;
69	char buf[sizeof("65000 ")];
70
71	UNUSED(tctx);
72
73	REQUIRE(rdata->type == 256);
74	REQUIRE(rdata->length != 0);
75
76	dns_rdata_toregion(rdata, &region);
77
78	/*
79	 * Priority
80	 */
81	priority = uint16_fromregion(&region);
82	isc_region_consume(&region, 2);
83	sprintf(buf, "%u ", priority);
84	RETERR(str_totext(buf, target));
85
86	/*
87	 * Weight
88	 */
89	weight = uint16_fromregion(&region);
90	isc_region_consume(&region, 2);
91	sprintf(buf, "%u ", weight);
92	RETERR(str_totext(buf, target));
93
94	/*
95	 * Target URI
96	 */
97	RETERR(multitxt_totext(&region, target));
98	return (ISC_R_SUCCESS);
99}
100
101static inline isc_result_t
102fromwire_uri(ARGS_FROMWIRE) {
103	isc_region_t region;
104
105	REQUIRE(type == 256);
106
107	UNUSED(type);
108	UNUSED(rdclass);
109	UNUSED(dctx);
110	UNUSED(options);
111
112	/*
113	 * Priority, weight
114	 */
115	isc_buffer_activeregion(source, &region);
116	if (region.length < 4)
117		return (ISC_R_UNEXPECTEDEND);
118	RETERR(mem_tobuffer(target, region.base, 4));
119	isc_buffer_forward(source, 4);
120
121	/*
122	 * Target URI
123	 */
124	RETERR(multitxt_fromwire(source, target));
125
126	return (ISC_R_SUCCESS);
127}
128
129static inline isc_result_t
130towire_uri(ARGS_TOWIRE) {
131	isc_region_t region;
132
133	REQUIRE(rdata->type == 256);
134	REQUIRE(rdata->length != 0);
135
136	UNUSED(cctx);
137
138	dns_rdata_toregion(rdata, &region);
139	return (mem_tobuffer(target, region.base, region.length));
140}
141
142static inline int
143compare_uri(ARGS_COMPARE) {
144	isc_region_t r1;
145	isc_region_t r2;
146	int order;
147
148	REQUIRE(rdata1->type == rdata2->type);
149	REQUIRE(rdata1->rdclass == rdata2->rdclass);
150	REQUIRE(rdata1->type == 256);
151	REQUIRE(rdata1->length != 0);
152	REQUIRE(rdata2->length != 0);
153
154	dns_rdata_toregion(rdata1, &r1);
155	dns_rdata_toregion(rdata2, &r2);
156
157	/*
158	 * Priority
159	 */
160	order = memcmp(r1.base, r2.base, 2);
161	if (order != 0)
162		return (order < 0 ? -1 : 1);
163	isc_region_consume(&r1, 2);
164	isc_region_consume(&r2, 2);
165
166	/*
167	 * Weight
168	 */
169	order = memcmp(r1.base, r2.base, 2);
170	if (order != 0)
171		return (order < 0 ? -1 : 1);
172	isc_region_consume(&r1, 2);
173	isc_region_consume(&r2, 2);
174
175	return (isc_region_compare(&r1, &r2));
176}
177
178static inline isc_result_t
179fromstruct_uri(ARGS_FROMSTRUCT) {
180	dns_rdata_uri_t *uri = source;
181	isc_region_t region;
182	isc_uint8_t len;
183
184	REQUIRE(type == 256);
185	REQUIRE(source != NULL);
186	REQUIRE(uri->common.rdtype == type);
187	REQUIRE(uri->common.rdclass == rdclass);
188	REQUIRE(uri->target != NULL && uri->tgt_len != 0);
189
190	UNUSED(type);
191	UNUSED(rdclass);
192
193	/*
194	 * Priority
195	 */
196	RETERR(uint16_tobuffer(uri->priority, target));
197
198	/*
199	 * Weight
200	 */
201	RETERR(uint16_tobuffer(uri->weight, target));
202
203	/*
204	 * Target URI
205	 */
206	len = 255U;
207	region.base = uri->target;
208	region.length = uri->tgt_len;
209	while (region.length > 0) {
210		REQUIRE(len == 255U);
211		len = uint8_fromregion(&region);
212		isc_region_consume(&region, 1);
213		if (region.length < len)
214			return (ISC_R_UNEXPECTEDEND);
215		isc_region_consume(&region, len);
216	}
217
218	return (mem_tobuffer(target, uri->target, uri->tgt_len));
219}
220
221static inline isc_result_t
222tostruct_uri(ARGS_TOSTRUCT) {
223	dns_rdata_uri_t *uri = target;
224	isc_region_t sr;
225
226	REQUIRE(rdata->type == 256);
227	REQUIRE(target != NULL);
228	REQUIRE(rdata->length != 0);
229
230	uri->common.rdclass = rdata->rdclass;
231	uri->common.rdtype = rdata->type;
232	ISC_LINK_INIT(&uri->common, link);
233
234	dns_rdata_toregion(rdata, &sr);
235
236	/*
237	 * Priority
238	 */
239	if (sr.length < 2)
240		return (ISC_R_UNEXPECTEDEND);
241	uri->priority = uint16_fromregion(&sr);
242	isc_region_consume(&sr, 2);
243
244	/*
245	 * Weight
246	 */
247	if (sr.length < 2)
248		return (ISC_R_UNEXPECTEDEND);
249	uri->weight = uint16_fromregion(&sr);
250	isc_region_consume(&sr, 2);
251
252	/*
253	 * Target URI
254	 */
255	uri->tgt_len = sr.length;
256	uri->target = mem_maybedup(mctx, sr.base, sr.length);
257	if (uri->target == NULL)
258		return (ISC_R_NOMEMORY);
259
260	uri->mctx = mctx;
261	return (ISC_R_SUCCESS);
262}
263
264static inline void
265freestruct_uri(ARGS_FREESTRUCT) {
266	dns_rdata_uri_t *uri = (dns_rdata_uri_t *) source;
267
268	REQUIRE(source != NULL);
269	REQUIRE(uri->common.rdtype == 256);
270
271	if (uri->mctx == NULL)
272		return;
273
274	if (uri->target != NULL)
275		isc_mem_free(uri->mctx, uri->target);
276	uri->mctx = NULL;
277}
278
279static inline isc_result_t
280additionaldata_uri(ARGS_ADDLDATA) {
281	REQUIRE(rdata->type == 256);
282
283	UNUSED(rdata);
284	UNUSED(add);
285	UNUSED(arg);
286
287	return (ISC_R_SUCCESS);
288}
289
290static inline isc_result_t
291digest_uri(ARGS_DIGEST) {
292	isc_region_t r;
293
294	REQUIRE(rdata->type == 256);
295
296	dns_rdata_toregion(rdata, &r);
297
298	return ((digest)(arg, &r));
299}
300
301static inline isc_boolean_t
302checkowner_uri(ARGS_CHECKOWNER) {
303
304	REQUIRE(type == 256);
305
306	UNUSED(name);
307	UNUSED(type);
308	UNUSED(rdclass);
309	UNUSED(wildcard);
310
311	return (ISC_TRUE);
312}
313
314static inline isc_boolean_t
315checknames_uri(ARGS_CHECKNAMES) {
316
317	REQUIRE(rdata->type == 256);
318
319	UNUSED(rdata);
320	UNUSED(owner);
321	UNUSED(bad);
322
323	return (ISC_TRUE);
324}
325
326static inline int
327casecompare_uri(ARGS_COMPARE) {
328	return (compare_uri(rdata1, rdata2));
329}
330
331#endif /* GENERIC_URI_256_C */
332