naptr_35.c 9.35 KB
Newer Older
Mark Andrews's avatar
Mark Andrews committed
1
/*
Bob Halley's avatar
Bob Halley committed
2
 * Copyright (C) 1999, 2000  Internet Software Consortium.
Mark Andrews's avatar
Mark Andrews committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

18
/* $Id: naptr_35.c,v 1.17 2000/03/17 02:47:01 bwelling Exp $ */
Mark Andrews's avatar
Mark Andrews committed
19

20 21 22
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */

/* RFC 2168 */
Mark Andrews's avatar
Mark Andrews committed
23

24 25
#ifndef RDATA_IN_1_NAPTR_35_C
#define RDATA_IN_1_NAPTR_35_C
Mark Andrews's avatar
Mark Andrews committed
26

27
static inline isc_result_t
28
fromtext_in_naptr(dns_rdataclass_t rdclass, dns_rdatatype_t type,
Mark Andrews's avatar
Mark Andrews committed
29 30
		  isc_lex_t *lexer, dns_name_t *origin,
		  isc_boolean_t downcase, isc_buffer_t *target)
Mark Andrews's avatar
Mark Andrews committed
31 32 33 34 35 36
{
	isc_token_t token;
	dns_name_t name;
	isc_buffer_t buffer;

	REQUIRE(type == 35);
37
	REQUIRE(rdclass == 1);
Mark Andrews's avatar
Mark Andrews committed
38

39
	/* order */
Mark Andrews's avatar
Mark Andrews committed
40 41 42
	RETERR(gettoken(lexer, &token, isc_tokentype_number, ISC_FALSE));
	RETERR(uint16_tobuffer(token.value.as_ulong, target));

43
	/* preference */
Mark Andrews's avatar
Mark Andrews committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
	RETERR(gettoken(lexer, &token, isc_tokentype_number, ISC_FALSE));
	RETERR(uint16_tobuffer(token.value.as_ulong, target));

	/* flags */
	RETERR(gettoken(lexer, &token, isc_tokentype_qstring, ISC_FALSE));
	RETERR(txt_fromtext(&token.value.as_textregion, target));

	/* service */
	RETERR(gettoken(lexer, &token, isc_tokentype_qstring, ISC_FALSE));
	RETERR(txt_fromtext(&token.value.as_textregion, target));

	/* regexp */
	RETERR(gettoken(lexer, &token, isc_tokentype_qstring, ISC_FALSE));
	RETERR(txt_fromtext(&token.value.as_textregion, target));

	/* replacement */
	RETERR(gettoken(lexer, &token, isc_tokentype_string, ISC_FALSE));
	dns_name_init(&name, NULL);
	buffer_fromregion(&buffer, &token.value.as_region,
			  ISC_BUFFERTYPE_TEXT);
	origin = (origin != NULL) ? origin : dns_rootname;
	return (dns_name_fromtext(&name, &buffer, origin, downcase, target));
}

68
static inline isc_result_t
69 70 71
totext_in_naptr(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, 
		isc_buffer_t *target) 
{
Mark Andrews's avatar
Mark Andrews committed
72 73 74 75 76 77 78 79
	isc_region_t region;
	dns_name_t name;
	dns_name_t prefix;
	isc_boolean_t sub;
	char buf[sizeof "64000"];
	unsigned short num;

	REQUIRE(rdata->type == 35);
80
	REQUIRE(rdata->rdclass == 1);
Mark Andrews's avatar
Mark Andrews committed
81 82 83 84 85

	dns_name_init(&name, NULL);
	dns_name_init(&prefix, NULL);

	dns_rdata_toregion(rdata, &region);
86 87

	/* order */
Mark Andrews's avatar
Mark Andrews committed
88 89 90 91 92 93
	num = uint16_fromregion(&region);
	isc_region_consume(&region, 2);
	sprintf(buf, "%u", num);
	RETERR(str_totext(buf, target));
	RETERR(str_totext(" ", target));

94
	/* preference */
Mark Andrews's avatar
Mark Andrews committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
	num = uint16_fromregion(&region);
	isc_region_consume(&region, 2);
	sprintf(buf, "%u", num);
	RETERR(str_totext(buf, target));
	RETERR(str_totext(" ", target));

	/* flags */
	RETERR(txt_totext(&region, target));
	RETERR(str_totext(" ", target));

	/* service */
	RETERR(txt_totext(&region, target));
	RETERR(str_totext(" ", target));

	/* regexp */
	RETERR(txt_totext(&region, target));
	RETERR(str_totext(" ", target));

	/* replacement */
	dns_name_fromregion(&name, &region);
115
	sub = name_prefix(&name, tctx->origin, &prefix);
116
	return (dns_name_totext(&prefix, sub, target));
Mark Andrews's avatar
Mark Andrews committed
117 118
}

119
static inline isc_result_t
120
fromwire_in_naptr(dns_rdataclass_t rdclass, dns_rdatatype_t type,
Mark Andrews's avatar
Mark Andrews committed
121 122
		  isc_buffer_t *source, dns_decompress_t *dctx,
		  isc_boolean_t downcase, isc_buffer_t *target)
Mark Andrews's avatar
Mark Andrews committed
123 124 125 126 127
{
        dns_name_t name;
	isc_region_t sr;

	REQUIRE(type == 35);
128
	REQUIRE(rdclass == 1);
Mark Andrews's avatar
Mark Andrews committed
129 130 131 132 133

	if (dns_decompress_edns(dctx) >= 1 || !dns_decompress_strict(dctx))
		dns_decompress_setmethods(dctx, DNS_COMPRESS_ALL);
	else
		dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
Mark Andrews's avatar
Mark Andrews committed
134 135 136
        
        dns_name_init(&name, NULL);

137
	/* order, preference */
Mark Andrews's avatar
Mark Andrews committed
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
	isc_buffer_active(source, &sr);
	if (sr.length < 4)
		return (DNS_R_UNEXPECTEDEND);
	RETERR(mem_tobuffer(target, sr.base, 4));
	isc_buffer_forward(source, 4);

	/* flags */
	RETERR(txt_fromwire(source, target));

	/* service */
	RETERR(txt_fromwire(source, target));

	/* regexp */
	RETERR(txt_fromwire(source, target));

	/* replacement */
	return (dns_name_fromwire(&name, source, dctx, downcase, target));
}

157
static inline isc_result_t
Mark Andrews's avatar
Mark Andrews committed
158 159 160 161 162
towire_in_naptr(dns_rdata_t *rdata, dns_compress_t *cctx, isc_buffer_t *target) {
	dns_name_t name;
	isc_region_t sr;

	REQUIRE(rdata->type == 35);
163
	REQUIRE(rdata->rdclass == 1);
Mark Andrews's avatar
Mark Andrews committed
164

Mark Andrews's avatar
Mark Andrews committed
165 166 167 168 169
	if (dns_compress_getedns(cctx) >= 1)
		dns_compress_setmethods(cctx, DNS_COMPRESS_ALL);
	else
		dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);

170
	/* order, preference */
Mark Andrews's avatar
Mark Andrews committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
	dns_rdata_toregion(rdata, &sr);
	RETERR(mem_tobuffer(target, sr.base, 4));
	isc_region_consume(&sr, 4);
	
	/* flags */
	RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
	isc_region_consume(&sr, sr.base[0] + 1);

	/* service */
	RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
	isc_region_consume(&sr, sr.base[0] + 1);

	/* regexp */
	RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
	isc_region_consume(&sr, sr.base[0] + 1);

	/* replacement */
	dns_name_init(&name, NULL);
	dns_name_fromregion(&name, &sr);
	return (dns_name_towire(&name, cctx, target));
}

193
static inline int
Mark Andrews's avatar
Mark Andrews committed
194 195 196 197 198
compare_in_naptr(dns_rdata_t *rdata1, dns_rdata_t *rdata2) {
	dns_name_t name1;
	dns_name_t name2;
	isc_region_t region1;
	isc_region_t region2;
199
	int result, len;
Mark Andrews's avatar
Mark Andrews committed
200 201

	REQUIRE(rdata1->type == rdata2->type);
202
	REQUIRE(rdata1->rdclass == rdata2->rdclass);
Mark Andrews's avatar
Mark Andrews committed
203
	REQUIRE(rdata1->type == 35);
204
	REQUIRE(rdata1->rdclass == 1);
Mark Andrews's avatar
Mark Andrews committed
205 206 207 208

	dns_rdata_toregion(rdata1, &region1);
	dns_rdata_toregion(rdata2, &region2);

209
	/* order, preference */
Mark Andrews's avatar
Mark Andrews committed
210 211 212 213 214 215 216
	result = memcmp(region1.base, region2.base, 4);
	if (result != 0)
		return (result < 0 ? -1 : 1);
	isc_region_consume(&region1, 4);
	isc_region_consume(&region2, 4);

	/* flags */
217 218
	len = ISC_MIN(region1.base[0], region2.base[0]);
	result = memcmp(region1.base, region2.base, len + 1);
Mark Andrews's avatar
Mark Andrews committed
219 220 221 222 223 224
	if (result != 0)
		return (result < 0 ? -1 : 1);
	isc_region_consume(&region1, region1.base[0] + 1);
	isc_region_consume(&region2, region2.base[0] + 1);

	/* service */
225 226
	len = ISC_MIN(region1.base[0], region2.base[0]);
	result = memcmp(region1.base, region2.base, len + 1);
Mark Andrews's avatar
Mark Andrews committed
227 228 229 230 231 232
	if (result != 0)
		return (result < 0 ? -1 : 1);
	isc_region_consume(&region1, region1.base[0] + 1);
	isc_region_consume(&region2, region2.base[0] + 1);

	/* regexp */
233 234
	len = ISC_MIN(region1.base[0], region2.base[0]);
	result = memcmp(region1.base, region2.base, len + 1);
Mark Andrews's avatar
Mark Andrews committed
235 236 237 238 239 240 241 242 243 244 245 246
	if (result != 0)
		return (result < 0 ? -1 : 1);
	isc_region_consume(&region1, region1.base[0] + 1);
	isc_region_consume(&region2, region2.base[0] + 1);

	/* replacement */
	dns_name_init(&name1, NULL);
	dns_name_init(&name2, NULL);

	dns_name_fromregion(&name1, &region1);
	dns_name_fromregion(&name2, &region2);

247
	return (dns_name_rdatacompare(&name1, &name2));
Mark Andrews's avatar
Mark Andrews committed
248 249
}

250
static inline isc_result_t
251
fromstruct_in_naptr(dns_rdataclass_t rdclass, dns_rdatatype_t type,
Mark Andrews's avatar
Mark Andrews committed
252
		    void *source, isc_buffer_t *target)
Mark Andrews's avatar
Mark Andrews committed
253
{
254 255
	UNUSED(source);
	UNUSED(target);
Mark Andrews's avatar
Mark Andrews committed
256 257

	REQUIRE(type == 35);
258
	REQUIRE(rdclass == 1);
Mark Andrews's avatar
Mark Andrews committed
259 260 261 262

	return (DNS_R_NOTIMPLEMENTED);
}

263
static inline isc_result_t
264
tostruct_in_naptr(dns_rdata_t *rdata, void *target, isc_mem_t *mctx) {
265 266
	UNUSED(target);
	UNUSED(mctx);
Mark Andrews's avatar
Mark Andrews committed
267 268

	REQUIRE(rdata->type == 35);
269
	REQUIRE(rdata->rdclass == 1);
Mark Andrews's avatar
Mark Andrews committed
270 271 272

	return (DNS_R_NOTIMPLEMENTED);
}
273

274
static inline void
275 276 277 278
freestruct_in_naptr(void *source) {
	REQUIRE(source != NULL);
	REQUIRE(ISC_FALSE);
}
279

280
static inline isc_result_t
281 282 283
additionaldata_in_naptr(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
			void *arg)
{
Bob Halley's avatar
Bob Halley committed
284 285 286 287 288 289
	dns_name_t name;
	isc_region_t sr;
	dns_rdatatype_t atype;
	unsigned int i, flagslen;
	char *cp;

290 291 292
	REQUIRE(rdata->type == 35);
	REQUIRE(rdata->rdclass == 1);

293
	/* order, preference */
Bob Halley's avatar
Bob Halley committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
	dns_rdata_toregion(rdata, &sr);
	isc_region_consume(&sr, 4);
	
	/* flags */
	atype = 0;
	flagslen = sr.base[0];
	cp = (char *)&sr.base[1];
	for (i = 0; i < flagslen; i++, cp++) {
		if (*cp == 'S' || *cp == 's') {
			atype = dns_rdatatype_srv;
			break;
		}
		if (*cp == 'A' || *cp == 'a') {
			atype = dns_rdatatype_a;
			break;
		}
	}
	isc_region_consume(&sr, flagslen + 1);

	/* service */
	isc_region_consume(&sr, sr.base[0] + 1);

	/* regexp */
	isc_region_consume(&sr, sr.base[0] + 1);

	/* replacement */
	dns_name_init(&name, NULL);
	dns_name_fromregion(&name, &sr);

	if (atype != 0)
		return ((add)(arg, &name, atype));
325 326 327 328

	return (DNS_R_SUCCESS);
}

329
static inline isc_result_t
330 331 332
digest_in_naptr(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) {
	isc_region_t r1, r2;
	unsigned int length, n;
333
	isc_result_t result;
334 335 336 337 338 339 340 341 342
	dns_name_t name;

	REQUIRE(rdata->type == 35);
	REQUIRE(rdata->rdclass == 1);

	dns_rdata_toregion(rdata, &r1);
	r2 = r1;
	length = 0;

343
	/* order, preference */
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
	length += 4;
	isc_region_consume(&r2, 4);

	/* flags */
	n = r2.base[0] + 1;
	length += n;
	isc_region_consume(&r2, n);

	/* service */
	n = r2.base[0] + 1;
	length += n;
	isc_region_consume(&r2, n);

	/* regexp */
	n = r2.base[0] + 1;
	length += n;
	isc_region_consume(&r2, n);

	/*
	 * Digest the RR up to the replacement name.
	 */
	r1.length = length;
	result = (digest)(arg, &r1);
	if (result != DNS_R_SUCCESS)
		return (result);

	/* replacement */

	dns_name_init(&name, NULL);
	dns_name_fromregion(&name, &r2);
	
	return (dns_name_digest(&name, digest, arg));
}

378
#endif	/* RDATA_IN_1_NAPTR_35_C */