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