]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/dns/rdata/in_1/naptr_35.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / dns / rdata / in_1 / naptr_35.c
1 /*
2  * Copyright (C) 2004, 2005, 2007-2009, 2012  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$ */
19
20 /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
21
22 /* RFC2915 */
23
24 #ifndef RDATA_IN_1_NAPTR_35_C
25 #define RDATA_IN_1_NAPTR_35_C
26
27 #define RRTYPE_NAPTR_ATTRIBUTES (0)
28 #ifdef HAVE_REGEX_H
29 #include <regex.h>
30 #endif
31
32 /*
33  * Check the wire format of the Regexp field.
34  * Don't allow embeded NUL's.
35  */
36 static inline isc_result_t
37 txt_valid_regex(const unsigned char *txt) {
38 #ifdef HAVE_REGEX_H
39         regex_t preg;
40         unsigned int regflags = REG_EXTENDED;
41         unsigned int nsub = 0;
42         char regex[256];
43         char *cp;
44 #endif
45         isc_boolean_t flags = ISC_FALSE;
46         isc_boolean_t replace = ISC_FALSE;
47         unsigned char c;
48         unsigned char delim;
49         unsigned int len;
50
51         len = *txt++;
52         if (len == 0U)
53                 return (ISC_R_SUCCESS);
54
55         delim = *txt++;
56         len--;
57
58         /*
59          * Digits, backslash and flags can't be delimiters.
60          */
61         switch (delim) {
62         case '0': case '1': case '2': case '3': case '4':
63         case '5': case '6': case '7': case '8': case '9':
64         case '\\': case 'i': case 0:
65                 return (DNS_R_SYNTAX);
66         }
67
68 #ifdef HAVE_REGEX_H
69         memset(&preg, 0, sizeof(preg));
70         cp = regex;
71 #endif
72
73         while (len-- > 0) {
74                 c = *txt++;
75                 if (c == 0)
76                         return (DNS_R_SYNTAX);
77                 if (c == delim && !replace) {
78                         replace = ISC_TRUE;
79                         continue;
80                 } else if (c == delim && !flags) {
81                         flags = ISC_TRUE;
82                         continue;
83                 } else if (c == delim)
84                         return (DNS_R_SYNTAX);
85                 /*
86                  * Flags are not escaped.
87                  */
88                 if (flags) {
89                         switch (c) {
90                         case 'i':
91 #ifdef HAVE_REGEX_H
92                                 regflags |= REG_ICASE;
93 #endif
94                                 continue;
95                         default:
96                                 return (DNS_R_SYNTAX);
97                         }
98                 }
99 #ifdef HAVE_REGEX_H
100                 if (!replace)
101                         *cp++ = c;
102 #endif
103                 if (c == '\\') {
104                         if (len == 0)
105                                 return (DNS_R_SYNTAX);
106                         c = *txt++;
107                         if (c == 0)
108                                 return (DNS_R_SYNTAX);
109                         len--;
110                         if (replace)
111                                 switch (c) {
112                                 case '0': return (DNS_R_SYNTAX);
113 #ifdef HAVE_REGEX_H
114                                 case '1': if (nsub < 1) nsub = 1; break;
115                                 case '2': if (nsub < 2) nsub = 2; break;
116                                 case '3': if (nsub < 3) nsub = 3; break;
117                                 case '4': if (nsub < 4) nsub = 4; break;
118                                 case '5': if (nsub < 5) nsub = 5; break;
119                                 case '6': if (nsub < 6) nsub = 6; break;
120                                 case '7': if (nsub < 7) nsub = 7; break;
121                                 case '8': if (nsub < 8) nsub = 8; break;
122                                 case '9': if (nsub < 9) nsub = 9; break;
123 #endif
124                                 }
125 #ifdef HAVE_REGEX_H
126                         if (!replace)
127                                 *cp++ = c;
128 #endif
129                 }
130         }
131         if (!flags)
132                 return (DNS_R_SYNTAX);
133 #ifdef HAVE_REGEX_H
134         *cp = '\0';
135         if (regcomp(&preg, regex, regflags))
136                 return (DNS_R_SYNTAX);
137         /*
138          * Check that substitutions in the replacement string are consistant
139          * with the regular expression.
140          */
141         if (preg.re_nsub < nsub) {
142                 regfree(&preg);
143                 return (DNS_R_SYNTAX);
144         }
145         regfree(&preg);
146 #endif
147         return (ISC_R_SUCCESS);
148 }
149
150 static inline isc_result_t
151 fromtext_in_naptr(ARGS_FROMTEXT) {
152         isc_token_t token;
153         dns_name_t name;
154         isc_buffer_t buffer;
155         unsigned char *regex;
156
157         REQUIRE(type == 35);
158         REQUIRE(rdclass == 1);
159
160         UNUSED(type);
161         UNUSED(rdclass);
162         UNUSED(callbacks);
163
164         /*
165          * Order.
166          */
167         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
168                                       ISC_FALSE));
169         if (token.value.as_ulong > 0xffffU)
170                 RETTOK(ISC_R_RANGE);
171         RETERR(uint16_tobuffer(token.value.as_ulong, target));
172
173         /*
174          * Preference.
175          */
176         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
177                                       ISC_FALSE));
178         if (token.value.as_ulong > 0xffffU)
179                 RETTOK(ISC_R_RANGE);
180         RETERR(uint16_tobuffer(token.value.as_ulong, target));
181
182         /*
183          * Flags.
184          */
185         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
186                                       ISC_FALSE));
187         RETTOK(txt_fromtext(&token.value.as_textregion, target));
188
189         /*
190          * Service.
191          */
192         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
193                                       ISC_FALSE));
194         RETTOK(txt_fromtext(&token.value.as_textregion, target));
195
196         /*
197          * Regexp.
198          */
199         regex = isc_buffer_used(target);
200         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
201                                       ISC_FALSE));
202         RETTOK(txt_fromtext(&token.value.as_textregion, target));
203         RETTOK(txt_valid_regex(regex));
204
205         /*
206          * Replacement.
207          */
208         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
209                                       ISC_FALSE));
210         dns_name_init(&name, NULL);
211         buffer_fromregion(&buffer, &token.value.as_region);
212         origin = (origin != NULL) ? origin : dns_rootname;
213         RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
214         return (ISC_R_SUCCESS);
215 }
216
217 static inline isc_result_t
218 totext_in_naptr(ARGS_TOTEXT) {
219         isc_region_t region;
220         dns_name_t name;
221         dns_name_t prefix;
222         isc_boolean_t sub;
223         char buf[sizeof("64000")];
224         unsigned short num;
225
226         REQUIRE(rdata->type == 35);
227         REQUIRE(rdata->rdclass == 1);
228         REQUIRE(rdata->length != 0);
229
230         dns_name_init(&name, NULL);
231         dns_name_init(&prefix, NULL);
232
233         dns_rdata_toregion(rdata, &region);
234
235         /*
236          * Order.
237          */
238         num = uint16_fromregion(&region);
239         isc_region_consume(&region, 2);
240         sprintf(buf, "%u", num);
241         RETERR(str_totext(buf, target));
242         RETERR(str_totext(" ", target));
243
244         /*
245          * Preference.
246          */
247         num = uint16_fromregion(&region);
248         isc_region_consume(&region, 2);
249         sprintf(buf, "%u", num);
250         RETERR(str_totext(buf, target));
251         RETERR(str_totext(" ", target));
252
253         /*
254          * Flags.
255          */
256         RETERR(txt_totext(&region, target));
257         RETERR(str_totext(" ", target));
258
259         /*
260          * Service.
261          */
262         RETERR(txt_totext(&region, target));
263         RETERR(str_totext(" ", target));
264
265         /*
266          * Regexp.
267          */
268         RETERR(txt_totext(&region, target));
269         RETERR(str_totext(" ", target));
270
271         /*
272          * Replacement.
273          */
274         dns_name_fromregion(&name, &region);
275         sub = name_prefix(&name, tctx->origin, &prefix);
276         return (dns_name_totext(&prefix, sub, target));
277 }
278
279 static inline isc_result_t
280 fromwire_in_naptr(ARGS_FROMWIRE) {
281         dns_name_t name;
282         isc_region_t sr;
283         unsigned char *regex;
284
285         REQUIRE(type == 35);
286         REQUIRE(rdclass == 1);
287
288         UNUSED(type);
289         UNUSED(rdclass);
290
291         dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
292
293         dns_name_init(&name, NULL);
294
295         /*
296          * Order, preference.
297          */
298         isc_buffer_activeregion(source, &sr);
299         if (sr.length < 4)
300                 return (ISC_R_UNEXPECTEDEND);
301         RETERR(mem_tobuffer(target, sr.base, 4));
302         isc_buffer_forward(source, 4);
303
304         /*
305          * Flags.
306          */
307         RETERR(txt_fromwire(source, target));
308
309         /*
310          * Service.
311          */
312         RETERR(txt_fromwire(source, target));
313
314         /*
315          * Regexp.
316          */
317         regex = isc_buffer_used(target);
318         RETERR(txt_fromwire(source, target));
319         RETERR(txt_valid_regex(regex));
320
321         /*
322          * Replacement.
323          */
324         return (dns_name_fromwire(&name, source, dctx, options, target));
325 }
326
327 static inline isc_result_t
328 towire_in_naptr(ARGS_TOWIRE) {
329         dns_name_t name;
330         dns_offsets_t offsets;
331         isc_region_t sr;
332
333         REQUIRE(rdata->type == 35);
334         REQUIRE(rdata->rdclass == 1);
335         REQUIRE(rdata->length != 0);
336
337         dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
338         /*
339          * Order, preference.
340          */
341         dns_rdata_toregion(rdata, &sr);
342         RETERR(mem_tobuffer(target, sr.base, 4));
343         isc_region_consume(&sr, 4);
344
345         /*
346          * Flags.
347          */
348         RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
349         isc_region_consume(&sr, sr.base[0] + 1);
350
351         /*
352          * Service.
353          */
354         RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
355         isc_region_consume(&sr, sr.base[0] + 1);
356
357         /*
358          * Regexp.
359          */
360         RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
361         isc_region_consume(&sr, sr.base[0] + 1);
362
363         /*
364          * Replacement.
365          */
366         dns_name_init(&name, offsets);
367         dns_name_fromregion(&name, &sr);
368         return (dns_name_towire(&name, cctx, target));
369 }
370
371 static inline int
372 compare_in_naptr(ARGS_COMPARE) {
373         dns_name_t name1;
374         dns_name_t name2;
375         isc_region_t region1;
376         isc_region_t region2;
377         int order, len;
378
379         REQUIRE(rdata1->type == rdata2->type);
380         REQUIRE(rdata1->rdclass == rdata2->rdclass);
381         REQUIRE(rdata1->type == 35);
382         REQUIRE(rdata1->rdclass == 1);
383         REQUIRE(rdata1->length != 0);
384         REQUIRE(rdata2->length != 0);
385
386         dns_rdata_toregion(rdata1, &region1);
387         dns_rdata_toregion(rdata2, &region2);
388
389         /*
390          * Order, preference.
391          */
392         order = memcmp(region1.base, region2.base, 4);
393         if (order != 0)
394                 return (order < 0 ? -1 : 1);
395         isc_region_consume(&region1, 4);
396         isc_region_consume(&region2, 4);
397
398         /*
399          * Flags.
400          */
401         len = ISC_MIN(region1.base[0], region2.base[0]);
402         order = memcmp(region1.base, region2.base, len + 1);
403         if (order != 0)
404                 return (order < 0 ? -1 : 1);
405         isc_region_consume(&region1, region1.base[0] + 1);
406         isc_region_consume(&region2, region2.base[0] + 1);
407
408         /*
409          * Service.
410          */
411         len = ISC_MIN(region1.base[0], region2.base[0]);
412         order = memcmp(region1.base, region2.base, len + 1);
413         if (order != 0)
414                 return (order < 0 ? -1 : 1);
415         isc_region_consume(&region1, region1.base[0] + 1);
416         isc_region_consume(&region2, region2.base[0] + 1);
417
418         /*
419          * Regexp.
420          */
421         len = ISC_MIN(region1.base[0], region2.base[0]);
422         order = memcmp(region1.base, region2.base, len + 1);
423         if (order != 0)
424                 return (order < 0 ? -1 : 1);
425         isc_region_consume(&region1, region1.base[0] + 1);
426         isc_region_consume(&region2, region2.base[0] + 1);
427
428         /*
429          * Replacement.
430          */
431         dns_name_init(&name1, NULL);
432         dns_name_init(&name2, NULL);
433
434         dns_name_fromregion(&name1, &region1);
435         dns_name_fromregion(&name2, &region2);
436
437         return (dns_name_rdatacompare(&name1, &name2));
438 }
439
440 static inline isc_result_t
441 fromstruct_in_naptr(ARGS_FROMSTRUCT) {
442         dns_rdata_in_naptr_t *naptr = source;
443         isc_region_t region;
444
445         REQUIRE(type == 35);
446         REQUIRE(rdclass == 1);
447         REQUIRE(source != NULL);
448         REQUIRE(naptr->common.rdtype == type);
449         REQUIRE(naptr->common.rdclass == rdclass);
450         REQUIRE(naptr->flags != NULL || naptr->flags_len == 0);
451         REQUIRE(naptr->service != NULL || naptr->service_len == 0);
452         REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0);
453
454         UNUSED(type);
455         UNUSED(rdclass);
456
457         RETERR(uint16_tobuffer(naptr->order, target));
458         RETERR(uint16_tobuffer(naptr->preference, target));
459         RETERR(uint8_tobuffer(naptr->flags_len, target));
460         RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len));
461         RETERR(uint8_tobuffer(naptr->service_len, target));
462         RETERR(mem_tobuffer(target, naptr->service, naptr->service_len));
463         RETERR(uint8_tobuffer(naptr->regexp_len, target));
464         RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len));
465         dns_name_toregion(&naptr->replacement, &region);
466         return (isc_buffer_copyregion(target, &region));
467 }
468
469 static inline isc_result_t
470 tostruct_in_naptr(ARGS_TOSTRUCT) {
471         dns_rdata_in_naptr_t *naptr = target;
472         isc_region_t r;
473         isc_result_t result;
474         dns_name_t name;
475
476         REQUIRE(rdata->type == 35);
477         REQUIRE(rdata->rdclass == 1);
478         REQUIRE(target != NULL);
479         REQUIRE(rdata->length != 0);
480
481         naptr->common.rdclass = rdata->rdclass;
482         naptr->common.rdtype = rdata->type;
483         ISC_LINK_INIT(&naptr->common, link);
484
485         naptr->flags = NULL;
486         naptr->service = NULL;
487         naptr->regexp = NULL;
488
489         dns_rdata_toregion(rdata, &r);
490
491         naptr->order = uint16_fromregion(&r);
492         isc_region_consume(&r, 2);
493
494         naptr->preference = uint16_fromregion(&r);
495         isc_region_consume(&r, 2);
496
497         naptr->flags_len = uint8_fromregion(&r);
498         isc_region_consume(&r, 1);
499         INSIST(naptr->flags_len <= r.length);
500         naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len);
501         if (naptr->flags == NULL)
502                 goto cleanup;
503         isc_region_consume(&r, naptr->flags_len);
504
505         naptr->service_len = uint8_fromregion(&r);
506         isc_region_consume(&r, 1);
507         INSIST(naptr->service_len <= r.length);
508         naptr->service = mem_maybedup(mctx, r.base, naptr->service_len);
509         if (naptr->service == NULL)
510                 goto cleanup;
511         isc_region_consume(&r, naptr->service_len);
512
513         naptr->regexp_len = uint8_fromregion(&r);
514         isc_region_consume(&r, 1);
515         INSIST(naptr->regexp_len <= r.length);
516         naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len);
517         if (naptr->regexp == NULL)
518                 goto cleanup;
519         isc_region_consume(&r, naptr->regexp_len);
520
521         dns_name_init(&name, NULL);
522         dns_name_fromregion(&name, &r);
523         dns_name_init(&naptr->replacement, NULL);
524         result = name_duporclone(&name, mctx, &naptr->replacement);
525         if (result != ISC_R_SUCCESS)
526                 goto cleanup;
527         naptr->mctx = mctx;
528         return (ISC_R_SUCCESS);
529
530  cleanup:
531         if (mctx != NULL && naptr->flags != NULL)
532                 isc_mem_free(mctx, naptr->flags);
533         if (mctx != NULL && naptr->service != NULL)
534                 isc_mem_free(mctx, naptr->service);
535         if (mctx != NULL && naptr->regexp != NULL)
536                 isc_mem_free(mctx, naptr->regexp);
537         return (ISC_R_NOMEMORY);
538 }
539
540 static inline void
541 freestruct_in_naptr(ARGS_FREESTRUCT) {
542         dns_rdata_in_naptr_t *naptr = source;
543
544         REQUIRE(source != NULL);
545         REQUIRE(naptr->common.rdclass == 1);
546         REQUIRE(naptr->common.rdtype == 35);
547
548         if (naptr->mctx == NULL)
549                 return;
550
551         if (naptr->flags != NULL)
552                 isc_mem_free(naptr->mctx, naptr->flags);
553         if (naptr->service != NULL)
554                 isc_mem_free(naptr->mctx, naptr->service);
555         if (naptr->regexp != NULL)
556                 isc_mem_free(naptr->mctx, naptr->regexp);
557         dns_name_free(&naptr->replacement, naptr->mctx);
558         naptr->mctx = NULL;
559 }
560
561 static inline isc_result_t
562 additionaldata_in_naptr(ARGS_ADDLDATA) {
563         dns_name_t name;
564         dns_offsets_t offsets;
565         isc_region_t sr;
566         dns_rdatatype_t atype;
567         unsigned int i, flagslen;
568         char *cp;
569
570         REQUIRE(rdata->type == 35);
571         REQUIRE(rdata->rdclass == 1);
572
573         /*
574          * Order, preference.
575          */
576         dns_rdata_toregion(rdata, &sr);
577         isc_region_consume(&sr, 4);
578
579         /*
580          * Flags.
581          */
582         atype = 0;
583         flagslen = sr.base[0];
584         cp = (char *)&sr.base[1];
585         for (i = 0; i < flagslen; i++, cp++) {
586                 if (*cp == 'S' || *cp == 's') {
587                         atype = dns_rdatatype_srv;
588                         break;
589                 }
590                 if (*cp == 'A' || *cp == 'a') {
591                         atype = dns_rdatatype_a;
592                         break;
593                 }
594         }
595         isc_region_consume(&sr, flagslen + 1);
596
597         /*
598          * Service.
599          */
600         isc_region_consume(&sr, sr.base[0] + 1);
601
602         /*
603          * Regexp.
604          */
605         isc_region_consume(&sr, sr.base[0] + 1);
606
607         /*
608          * Replacement.
609          */
610         dns_name_init(&name, offsets);
611         dns_name_fromregion(&name, &sr);
612
613         if (atype != 0)
614                 return ((add)(arg, &name, atype));
615
616         return (ISC_R_SUCCESS);
617 }
618
619 static inline isc_result_t
620 digest_in_naptr(ARGS_DIGEST) {
621         isc_region_t r1, r2;
622         unsigned int length, n;
623         isc_result_t result;
624         dns_name_t name;
625
626         REQUIRE(rdata->type == 35);
627         REQUIRE(rdata->rdclass == 1);
628
629         dns_rdata_toregion(rdata, &r1);
630         r2 = r1;
631         length = 0;
632
633         /*
634          * Order, preference.
635          */
636         length += 4;
637         isc_region_consume(&r2, 4);
638
639         /*
640          * Flags.
641          */
642         n = r2.base[0] + 1;
643         length += n;
644         isc_region_consume(&r2, n);
645
646         /*
647          * Service.
648          */
649         n = r2.base[0] + 1;
650         length += n;
651         isc_region_consume(&r2, n);
652
653         /*
654          * Regexp.
655          */
656         n = r2.base[0] + 1;
657         length += n;
658         isc_region_consume(&r2, n);
659
660         /*
661          * Digest the RR up to the replacement name.
662          */
663         r1.length = length;
664         result = (digest)(arg, &r1);
665         if (result != ISC_R_SUCCESS)
666                 return (result);
667
668         /*
669          * Replacement.
670          */
671
672         dns_name_init(&name, NULL);
673         dns_name_fromregion(&name, &r2);
674
675         return (dns_name_digest(&name, digest, arg));
676 }
677
678 static inline isc_boolean_t
679 checkowner_in_naptr(ARGS_CHECKOWNER) {
680
681         REQUIRE(type == 35);
682         REQUIRE(rdclass == 1);
683
684         UNUSED(name);
685         UNUSED(type);
686         UNUSED(rdclass);
687         UNUSED(wildcard);
688
689         return (ISC_TRUE);
690 }
691
692 static inline isc_boolean_t
693 checknames_in_naptr(ARGS_CHECKNAMES) {
694
695         REQUIRE(rdata->type == 35);
696         REQUIRE(rdata->rdclass == 1);
697
698         UNUSED(rdata);
699         UNUSED(owner);
700         UNUSED(bad);
701
702         return (ISC_TRUE);
703 }
704
705 static inline int
706 casecompare_in_naptr(ARGS_COMPARE) {
707         return (compare_in_naptr(rdata1, rdata2));
708 }
709
710 #endif  /* RDATA_IN_1_NAPTR_35_C */