Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / rdata / in_1 / naptr_35.c
blob61d25f716ae61c6637896ef48dfb1dbcbdbdaa12
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: naptr_35.c,v 1.56 2009/12/04 21:09:34 marka Exp */
22 /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
24 /* RFC2915 */
26 #ifndef RDATA_IN_1_NAPTR_35_C
27 #define RDATA_IN_1_NAPTR_35_C
29 #define RRTYPE_NAPTR_ATTRIBUTES (0)
30 #ifdef HAVE_REGEX_H
31 #include <regex.h>
32 #endif
35 * Check the wire format of the Regexp field.
36 * Don't allow embeded NUL's.
38 static inline isc_result_t
39 txt_valid_regex(const unsigned char *txt) {
40 #ifdef HAVE_REGEX_H
41 regex_t preg;
42 unsigned int regflags = REG_EXTENDED;
43 unsigned int nsub = 0;
44 char regex[256];
45 char *cp;
46 #endif
47 isc_boolean_t flags = ISC_FALSE;
48 isc_boolean_t replace = ISC_FALSE;
49 unsigned char c;
50 unsigned char delim;
51 unsigned int len;
53 len = *txt++;
54 if (len == 0U)
55 return (ISC_R_SUCCESS);
57 delim = *txt++;
58 len--;
61 * Digits, backslash and flags can't be delimiters.
63 switch (delim) {
64 case '0': case '1': case '2': case '3': case '4':
65 case '5': case '6': case '7': case '8': case '9':
66 case '\\': case 'i': case 0:
67 return (DNS_R_SYNTAX);
70 #ifdef HAVE_REGEX_H
71 memset(&preg, 0, sizeof(preg));
72 cp = regex;
73 #endif
75 while (len-- > 0) {
76 c = *txt++;
77 if (c == 0)
78 return (DNS_R_SYNTAX);
79 if (c == delim && !replace) {
80 replace = ISC_TRUE;
81 continue;
82 } else if (c == delim && !flags) {
83 flags = ISC_TRUE;
84 continue;
85 } else if (c == delim)
86 return (DNS_R_SYNTAX);
88 * Flags are not escaped.
90 if (flags) {
91 switch (c) {
92 case 'i':
93 #ifdef HAVE_REGEX_H
94 regflags |= REG_ICASE;
95 #endif
96 continue;
97 default:
98 return (DNS_R_SYNTAX);
101 #ifdef HAVE_REGEX_H
102 if (!replace)
103 *cp++ = c;
104 #endif
105 if (c == '\\') {
106 if (len == 0)
107 return (DNS_R_SYNTAX);
108 c = *txt++;
109 if (c == 0)
110 return (DNS_R_SYNTAX);
111 len--;
112 if (replace)
113 switch (c) {
114 case '0': return (DNS_R_SYNTAX);
115 #ifdef HAVE_REGEX_H
116 case '1': if (nsub < 1) nsub = 1; break;
117 case '2': if (nsub < 2) nsub = 2; break;
118 case '3': if (nsub < 3) nsub = 3; break;
119 case '4': if (nsub < 4) nsub = 4; break;
120 case '5': if (nsub < 5) nsub = 5; break;
121 case '6': if (nsub < 6) nsub = 6; break;
122 case '7': if (nsub < 7) nsub = 7; break;
123 case '8': if (nsub < 8) nsub = 8; break;
124 case '9': if (nsub < 9) nsub = 9; break;
125 #endif
127 #ifdef HAVE_REGEX_H
128 if (!replace)
129 *cp++ = c;
130 #endif
133 if (!flags)
134 return (DNS_R_SYNTAX);
135 #ifdef HAVE_REGEX_H
136 *cp = '\0';
137 if (regcomp(&preg, regex, regflags))
138 return (DNS_R_SYNTAX);
140 * Check that substitutions in the replacement string are consistant
141 * with the regular expression.
143 if (preg.re_nsub < nsub) {
144 regfree(&preg);
145 return (DNS_R_SYNTAX);
147 regfree(&preg);
148 #endif
149 return (ISC_R_SUCCESS);
152 static inline isc_result_t
153 fromtext_in_naptr(ARGS_FROMTEXT) {
154 isc_token_t token;
155 dns_name_t name;
156 isc_buffer_t buffer;
157 unsigned char *regex;
159 REQUIRE(type == 35);
160 REQUIRE(rdclass == 1);
162 UNUSED(type);
163 UNUSED(rdclass);
164 UNUSED(callbacks);
167 * Order.
169 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
170 ISC_FALSE));
171 if (token.value.as_ulong > 0xffffU)
172 RETTOK(ISC_R_RANGE);
173 RETERR(uint16_tobuffer(token.value.as_ulong, target));
176 * Preference.
178 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
179 ISC_FALSE));
180 if (token.value.as_ulong > 0xffffU)
181 RETTOK(ISC_R_RANGE);
182 RETERR(uint16_tobuffer(token.value.as_ulong, target));
185 * Flags.
187 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
188 ISC_FALSE));
189 RETTOK(txt_fromtext(&token.value.as_textregion, target));
192 * Service.
194 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
195 ISC_FALSE));
196 RETTOK(txt_fromtext(&token.value.as_textregion, target));
199 * Regexp.
201 regex = isc_buffer_used(target);
202 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
203 ISC_FALSE));
204 RETTOK(txt_fromtext(&token.value.as_textregion, target));
205 RETTOK(txt_valid_regex(regex));
208 * Replacement.
210 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
211 ISC_FALSE));
212 dns_name_init(&name, NULL);
213 buffer_fromregion(&buffer, &token.value.as_region);
214 origin = (origin != NULL) ? origin : dns_rootname;
215 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
216 return (ISC_R_SUCCESS);
219 static inline isc_result_t
220 totext_in_naptr(ARGS_TOTEXT) {
221 isc_region_t region;
222 dns_name_t name;
223 dns_name_t prefix;
224 isc_boolean_t sub;
225 char buf[sizeof("64000")];
226 unsigned short num;
228 REQUIRE(rdata->type == 35);
229 REQUIRE(rdata->rdclass == 1);
230 REQUIRE(rdata->length != 0);
232 dns_name_init(&name, NULL);
233 dns_name_init(&prefix, NULL);
235 dns_rdata_toregion(rdata, &region);
238 * Order.
240 num = uint16_fromregion(&region);
241 isc_region_consume(&region, 2);
242 sprintf(buf, "%u", num);
243 RETERR(str_totext(buf, target));
244 RETERR(str_totext(" ", target));
247 * Preference.
249 num = uint16_fromregion(&region);
250 isc_region_consume(&region, 2);
251 sprintf(buf, "%u", num);
252 RETERR(str_totext(buf, target));
253 RETERR(str_totext(" ", target));
256 * Flags.
258 RETERR(txt_totext(&region, target));
259 RETERR(str_totext(" ", target));
262 * Service.
264 RETERR(txt_totext(&region, target));
265 RETERR(str_totext(" ", target));
268 * Regexp.
270 RETERR(txt_totext(&region, target));
271 RETERR(str_totext(" ", target));
274 * Replacement.
276 dns_name_fromregion(&name, &region);
277 sub = name_prefix(&name, tctx->origin, &prefix);
278 return (dns_name_totext(&prefix, sub, target));
281 static inline isc_result_t
282 fromwire_in_naptr(ARGS_FROMWIRE) {
283 dns_name_t name;
284 isc_region_t sr;
285 unsigned char *regex;
287 REQUIRE(type == 35);
288 REQUIRE(rdclass == 1);
290 UNUSED(type);
291 UNUSED(rdclass);
293 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
295 dns_name_init(&name, NULL);
298 * Order, preference.
300 isc_buffer_activeregion(source, &sr);
301 if (sr.length < 4)
302 return (ISC_R_UNEXPECTEDEND);
303 RETERR(mem_tobuffer(target, sr.base, 4));
304 isc_buffer_forward(source, 4);
307 * Flags.
309 RETERR(txt_fromwire(source, target));
312 * Service.
314 RETERR(txt_fromwire(source, target));
317 * Regexp.
319 regex = isc_buffer_used(target);
320 RETERR(txt_fromwire(source, target));
321 RETERR(txt_valid_regex(regex));
324 * Replacement.
326 return (dns_name_fromwire(&name, source, dctx, options, target));
329 static inline isc_result_t
330 towire_in_naptr(ARGS_TOWIRE) {
331 dns_name_t name;
332 dns_offsets_t offsets;
333 isc_region_t sr;
335 REQUIRE(rdata->type == 35);
336 REQUIRE(rdata->rdclass == 1);
337 REQUIRE(rdata->length != 0);
339 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
341 * Order, preference.
343 dns_rdata_toregion(rdata, &sr);
344 RETERR(mem_tobuffer(target, sr.base, 4));
345 isc_region_consume(&sr, 4);
348 * Flags.
350 RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
351 isc_region_consume(&sr, sr.base[0] + 1);
354 * Service.
356 RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
357 isc_region_consume(&sr, sr.base[0] + 1);
360 * Regexp.
362 RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
363 isc_region_consume(&sr, sr.base[0] + 1);
366 * Replacement.
368 dns_name_init(&name, offsets);
369 dns_name_fromregion(&name, &sr);
370 return (dns_name_towire(&name, cctx, target));
373 static inline int
374 compare_in_naptr(ARGS_COMPARE) {
375 dns_name_t name1;
376 dns_name_t name2;
377 isc_region_t region1;
378 isc_region_t region2;
379 int order, len;
381 REQUIRE(rdata1->type == rdata2->type);
382 REQUIRE(rdata1->rdclass == rdata2->rdclass);
383 REQUIRE(rdata1->type == 35);
384 REQUIRE(rdata1->rdclass == 1);
385 REQUIRE(rdata1->length != 0);
386 REQUIRE(rdata2->length != 0);
388 dns_rdata_toregion(rdata1, &region1);
389 dns_rdata_toregion(rdata2, &region2);
392 * Order, preference.
394 order = memcmp(region1.base, region2.base, 4);
395 if (order != 0)
396 return (order < 0 ? -1 : 1);
397 isc_region_consume(&region1, 4);
398 isc_region_consume(&region2, 4);
401 * Flags.
403 len = ISC_MIN(region1.base[0], region2.base[0]);
404 order = memcmp(region1.base, region2.base, len + 1);
405 if (order != 0)
406 return (order < 0 ? -1 : 1);
407 isc_region_consume(&region1, region1.base[0] + 1);
408 isc_region_consume(&region2, region2.base[0] + 1);
411 * Service.
413 len = ISC_MIN(region1.base[0], region2.base[0]);
414 order = memcmp(region1.base, region2.base, len + 1);
415 if (order != 0)
416 return (order < 0 ? -1 : 1);
417 isc_region_consume(&region1, region1.base[0] + 1);
418 isc_region_consume(&region2, region2.base[0] + 1);
421 * Regexp.
423 len = ISC_MIN(region1.base[0], region2.base[0]);
424 order = memcmp(region1.base, region2.base, len + 1);
425 if (order != 0)
426 return (order < 0 ? -1 : 1);
427 isc_region_consume(&region1, region1.base[0] + 1);
428 isc_region_consume(&region2, region2.base[0] + 1);
431 * Replacement.
433 dns_name_init(&name1, NULL);
434 dns_name_init(&name2, NULL);
436 dns_name_fromregion(&name1, &region1);
437 dns_name_fromregion(&name2, &region2);
439 return (dns_name_rdatacompare(&name1, &name2));
442 static inline isc_result_t
443 fromstruct_in_naptr(ARGS_FROMSTRUCT) {
444 dns_rdata_in_naptr_t *naptr = source;
445 isc_region_t region;
447 REQUIRE(type == 35);
448 REQUIRE(rdclass == 1);
449 REQUIRE(source != NULL);
450 REQUIRE(naptr->common.rdtype == type);
451 REQUIRE(naptr->common.rdclass == rdclass);
452 REQUIRE(naptr->flags != NULL || naptr->flags_len == 0);
453 REQUIRE(naptr->service != NULL || naptr->service_len == 0);
454 REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0);
456 UNUSED(type);
457 UNUSED(rdclass);
459 RETERR(uint16_tobuffer(naptr->order, target));
460 RETERR(uint16_tobuffer(naptr->preference, target));
461 RETERR(uint8_tobuffer(naptr->flags_len, target));
462 RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len));
463 RETERR(uint8_tobuffer(naptr->service_len, target));
464 RETERR(mem_tobuffer(target, naptr->service, naptr->service_len));
465 RETERR(uint8_tobuffer(naptr->regexp_len, target));
466 RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len));
467 dns_name_toregion(&naptr->replacement, &region);
468 return (isc_buffer_copyregion(target, &region));
471 static inline isc_result_t
472 tostruct_in_naptr(ARGS_TOSTRUCT) {
473 dns_rdata_in_naptr_t *naptr = target;
474 isc_region_t r;
475 isc_result_t result;
476 dns_name_t name;
478 REQUIRE(rdata->type == 35);
479 REQUIRE(rdata->rdclass == 1);
480 REQUIRE(target != NULL);
481 REQUIRE(rdata->length != 0);
483 naptr->common.rdclass = rdata->rdclass;
484 naptr->common.rdtype = rdata->type;
485 ISC_LINK_INIT(&naptr->common, link);
487 naptr->flags = NULL;
488 naptr->service = NULL;
489 naptr->regexp = NULL;
491 dns_rdata_toregion(rdata, &r);
493 naptr->order = uint16_fromregion(&r);
494 isc_region_consume(&r, 2);
496 naptr->preference = uint16_fromregion(&r);
497 isc_region_consume(&r, 2);
499 naptr->flags_len = uint8_fromregion(&r);
500 isc_region_consume(&r, 1);
501 INSIST(naptr->flags_len <= r.length);
502 naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len);
503 if (naptr->flags == NULL)
504 goto cleanup;
505 isc_region_consume(&r, naptr->flags_len);
507 naptr->service_len = uint8_fromregion(&r);
508 isc_region_consume(&r, 1);
509 INSIST(naptr->service_len <= r.length);
510 naptr->service = mem_maybedup(mctx, r.base, naptr->service_len);
511 if (naptr->service == NULL)
512 goto cleanup;
513 isc_region_consume(&r, naptr->service_len);
515 naptr->regexp_len = uint8_fromregion(&r);
516 isc_region_consume(&r, 1);
517 INSIST(naptr->regexp_len <= r.length);
518 naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len);
519 if (naptr->regexp == NULL)
520 goto cleanup;
521 isc_region_consume(&r, naptr->regexp_len);
523 dns_name_init(&name, NULL);
524 dns_name_fromregion(&name, &r);
525 dns_name_init(&naptr->replacement, NULL);
526 result = name_duporclone(&name, mctx, &naptr->replacement);
527 if (result != ISC_R_SUCCESS)
528 goto cleanup;
529 naptr->mctx = mctx;
530 return (ISC_R_SUCCESS);
532 cleanup:
533 if (mctx != NULL && naptr->flags != NULL)
534 isc_mem_free(mctx, naptr->flags);
535 if (mctx != NULL && naptr->service != NULL)
536 isc_mem_free(mctx, naptr->service);
537 if (mctx != NULL && naptr->regexp != NULL)
538 isc_mem_free(mctx, naptr->regexp);
539 return (ISC_R_NOMEMORY);
542 static inline void
543 freestruct_in_naptr(ARGS_FREESTRUCT) {
544 dns_rdata_in_naptr_t *naptr = source;
546 REQUIRE(source != NULL);
547 REQUIRE(naptr->common.rdclass == 1);
548 REQUIRE(naptr->common.rdtype == 35);
550 if (naptr->mctx == NULL)
551 return;
553 if (naptr->flags != NULL)
554 isc_mem_free(naptr->mctx, naptr->flags);
555 if (naptr->service != NULL)
556 isc_mem_free(naptr->mctx, naptr->service);
557 if (naptr->regexp != NULL)
558 isc_mem_free(naptr->mctx, naptr->regexp);
559 dns_name_free(&naptr->replacement, naptr->mctx);
560 naptr->mctx = NULL;
563 static inline isc_result_t
564 additionaldata_in_naptr(ARGS_ADDLDATA) {
565 dns_name_t name;
566 dns_offsets_t offsets;
567 isc_region_t sr;
568 dns_rdatatype_t atype;
569 unsigned int i, flagslen;
570 char *cp;
572 REQUIRE(rdata->type == 35);
573 REQUIRE(rdata->rdclass == 1);
576 * Order, preference.
578 dns_rdata_toregion(rdata, &sr);
579 isc_region_consume(&sr, 4);
582 * Flags.
584 atype = 0;
585 flagslen = sr.base[0];
586 cp = (char *)&sr.base[1];
587 for (i = 0; i < flagslen; i++, cp++) {
588 if (*cp == 'S' || *cp == 's') {
589 atype = dns_rdatatype_srv;
590 break;
592 if (*cp == 'A' || *cp == 'a') {
593 atype = dns_rdatatype_a;
594 break;
597 isc_region_consume(&sr, flagslen + 1);
600 * Service.
602 isc_region_consume(&sr, sr.base[0] + 1);
605 * Regexp.
607 isc_region_consume(&sr, sr.base[0] + 1);
610 * Replacement.
612 dns_name_init(&name, offsets);
613 dns_name_fromregion(&name, &sr);
615 if (atype != 0)
616 return ((add)(arg, &name, atype));
618 return (ISC_R_SUCCESS);
621 static inline isc_result_t
622 digest_in_naptr(ARGS_DIGEST) {
623 isc_region_t r1, r2;
624 unsigned int length, n;
625 isc_result_t result;
626 dns_name_t name;
628 REQUIRE(rdata->type == 35);
629 REQUIRE(rdata->rdclass == 1);
631 dns_rdata_toregion(rdata, &r1);
632 r2 = r1;
633 length = 0;
636 * Order, preference.
638 length += 4;
639 isc_region_consume(&r2, 4);
642 * Flags.
644 n = r2.base[0] + 1;
645 length += n;
646 isc_region_consume(&r2, n);
649 * Service.
651 n = r2.base[0] + 1;
652 length += n;
653 isc_region_consume(&r2, n);
656 * Regexp.
658 n = r2.base[0] + 1;
659 length += n;
660 isc_region_consume(&r2, n);
663 * Digest the RR up to the replacement name.
665 r1.length = length;
666 result = (digest)(arg, &r1);
667 if (result != ISC_R_SUCCESS)
668 return (result);
671 * Replacement.
674 dns_name_init(&name, NULL);
675 dns_name_fromregion(&name, &r2);
677 return (dns_name_digest(&name, digest, arg));
680 static inline isc_boolean_t
681 checkowner_in_naptr(ARGS_CHECKOWNER) {
683 REQUIRE(type == 35);
684 REQUIRE(rdclass == 1);
686 UNUSED(name);
687 UNUSED(type);
688 UNUSED(rdclass);
689 UNUSED(wildcard);
691 return (ISC_TRUE);
694 static inline isc_boolean_t
695 checknames_in_naptr(ARGS_CHECKNAMES) {
697 REQUIRE(rdata->type == 35);
698 REQUIRE(rdata->rdclass == 1);
700 UNUSED(rdata);
701 UNUSED(owner);
702 UNUSED(bad);
704 return (ISC_TRUE);
707 static inline int
708 casecompare_in_naptr(ARGS_COMPARE) {
709 return (compare_in_naptr(rdata1, rdata2));
712 #endif /* RDATA_IN_1_NAPTR_35_C */