]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/rdata.c
Update to BIND 9.6.3, the latest from ISC on the 9.6 branch.
[FreeBSD/stable/8.git] / contrib / bind9 / lib / dns / rdata.c
1 /*
2  * Copyright (C) 2004-2009, 2011  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-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: rdata.c,v 1.199.50.4 2011-01-13 04:48:21 tbox Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23 #include <ctype.h>
24
25 #include <isc/base64.h>
26 #include <isc/hex.h>
27 #include <isc/lex.h>
28 #include <isc/mem.h>
29 #include <isc/parseint.h>
30 #include <isc/print.h>
31 #include <isc/string.h>
32 #include <isc/stdlib.h>
33 #include <isc/util.h>
34
35 #include <dns/callbacks.h>
36 #include <dns/cert.h>
37 #include <dns/compress.h>
38 #include <dns/enumtype.h>
39 #include <dns/keyflags.h>
40 #include <dns/keyvalues.h>
41 #include <dns/rcode.h>
42 #include <dns/rdata.h>
43 #include <dns/rdataclass.h>
44 #include <dns/rdatastruct.h>
45 #include <dns/rdatatype.h>
46 #include <dns/result.h>
47 #include <dns/secalg.h>
48 #include <dns/secproto.h>
49 #include <dns/time.h>
50 #include <dns/ttl.h>
51
52 #define RETERR(x) \
53         do { \
54                 isc_result_t _r = (x); \
55                 if (_r != ISC_R_SUCCESS) \
56                         return (_r); \
57         } while (0)
58
59 #define RETTOK(x) \
60         do { \
61                 isc_result_t _r = (x); \
62                 if (_r != ISC_R_SUCCESS) { \
63                         isc_lex_ungettoken(lexer, &token); \
64                         return (_r); \
65                 } \
66         } while (0)
67
68 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
69
70 #define ARGS_FROMTEXT   int rdclass, dns_rdatatype_t type, \
71                         isc_lex_t *lexer, dns_name_t *origin, \
72                         unsigned int options, isc_buffer_t *target, \
73                         dns_rdatacallbacks_t *callbacks
74
75 #define ARGS_TOTEXT     dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
76                         isc_buffer_t *target
77
78 #define ARGS_FROMWIRE   int rdclass, dns_rdatatype_t type, \
79                         isc_buffer_t *source, dns_decompress_t *dctx, \
80                         unsigned int options, isc_buffer_t *target
81
82 #define ARGS_TOWIRE     dns_rdata_t *rdata, dns_compress_t *cctx, \
83                         isc_buffer_t *target
84
85 #define ARGS_COMPARE    const dns_rdata_t *rdata1, const dns_rdata_t *rdata2
86
87 #define ARGS_FROMSTRUCT int rdclass, dns_rdatatype_t type, \
88                         void *source, isc_buffer_t *target
89
90 #define ARGS_TOSTRUCT   dns_rdata_t *rdata, void *target, isc_mem_t *mctx
91
92 #define ARGS_FREESTRUCT void *source
93
94 #define ARGS_ADDLDATA   dns_rdata_t *rdata, dns_additionaldatafunc_t add, \
95                         void *arg
96
97 #define ARGS_DIGEST     dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg
98
99 #define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \
100                         dns_rdatatype_t type, isc_boolean_t wildcard
101
102 #define ARGS_CHECKNAMES dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad
103
104
105 /*%
106  * Context structure for the totext_ functions.
107  * Contains formatting options for rdata-to-text
108  * conversion.
109  */
110 typedef struct dns_rdata_textctx {
111         dns_name_t *origin;     /*%< Current origin, or NULL. */
112         unsigned int flags;     /*%< DNS_STYLEFLAG_*  */
113         unsigned int width;     /*%< Width of rdata column. */
114         const char *linebreak;  /*%< Line break string. */
115 } dns_rdata_textctx_t;
116
117 static isc_result_t
118 txt_totext(isc_region_t *source, isc_buffer_t *target);
119
120 static isc_result_t
121 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
122
123 static isc_result_t
124 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
125
126 static isc_boolean_t
127 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
128
129 static unsigned int
130 name_length(dns_name_t *name);
131
132 static isc_result_t
133 str_totext(const char *source, isc_buffer_t *target);
134
135 static isc_result_t
136 inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
137
138 static isc_boolean_t
139 buffer_empty(isc_buffer_t *source);
140
141 static void
142 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region);
143
144 static isc_result_t
145 uint32_tobuffer(isc_uint32_t, isc_buffer_t *target);
146
147 static isc_result_t
148 uint16_tobuffer(isc_uint32_t, isc_buffer_t *target);
149
150 static isc_result_t
151 uint8_tobuffer(isc_uint32_t, isc_buffer_t *target);
152
153 static isc_result_t
154 name_tobuffer(dns_name_t *name, isc_buffer_t *target);
155
156 static isc_uint32_t
157 uint32_fromregion(isc_region_t *region);
158
159 static isc_uint16_t
160 uint16_fromregion(isc_region_t *region);
161
162 static isc_uint8_t
163 uint8_fromregion(isc_region_t *region);
164
165 static isc_uint8_t
166 uint8_consume_fromregion(isc_region_t *region);
167
168 static isc_result_t
169 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
170
171 static int
172 hexvalue(char value);
173
174 static int
175 decvalue(char value);
176
177 static isc_result_t
178 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
179
180 static isc_result_t
181 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target);
182
183 static void
184 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...)
185      ISC_FORMAT_PRINTF(2, 3);
186
187 static void
188 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
189                dns_rdatacallbacks_t *callbacks, const char *name,
190                unsigned long line, isc_token_t *token, isc_result_t result);
191
192 static void
193 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);
194
195 static isc_result_t
196 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
197              isc_buffer_t *target);
198
199 static void
200 warn_badname(dns_name_t *name, isc_lex_t *lexer,
201              dns_rdatacallbacks_t *callbacks);
202
203 static void
204 warn_badmx(isc_token_t *token, isc_lex_t *lexer,
205            dns_rdatacallbacks_t *callbacks);
206
207 static isc_uint16_t
208 uint16_consume_fromregion(isc_region_t *region);
209
210 static inline int
211 getquad(const void *src, struct in_addr *dst,
212         isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks)
213 {
214         int result;
215         struct in_addr *tmp;
216
217         result = inet_aton(src, dst);
218         if (result == 1 && callbacks != NULL &&
219             inet_pton(AF_INET, src, &tmp) != 1) {
220                 const char *name = isc_lex_getsourcename(lexer);
221                 if (name == NULL)
222                         name = "UNKNOWN";
223                 (*callbacks->warn)(callbacks, "%s:%lu: \"%s\" "
224                                    "is not a decimal dotted quad", name,
225                                    isc_lex_getsourceline(lexer), src);
226         }
227         return (result);
228 }
229
230 static inline isc_result_t
231 name_duporclone(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
232
233         if (mctx != NULL)
234                 return (dns_name_dup(source, mctx, target));
235         dns_name_clone(source, target);
236         return (ISC_R_SUCCESS);
237 }
238
239 static inline void *
240 mem_maybedup(isc_mem_t *mctx, void *source, size_t length) {
241         void *new;
242
243         if (mctx == NULL)
244                 return (source);
245         new = isc_mem_allocate(mctx, length);
246         if (new != NULL)
247                 memcpy(new, source, length);
248
249         return (new);
250 }
251
252 static const char hexdigits[] = "0123456789abcdef";
253 static const char decdigits[] = "0123456789";
254
255 #include "code.h"
256
257 #define META 0x0001
258 #define RESERVED 0x0002
259
260 /***
261  *** Initialization
262  ***/
263
264 void
265 dns_rdata_init(dns_rdata_t *rdata) {
266
267         REQUIRE(rdata != NULL);
268
269         rdata->data = NULL;
270         rdata->length = 0;
271         rdata->rdclass = 0;
272         rdata->type = 0;
273         rdata->flags = 0;
274         ISC_LINK_INIT(rdata, link);
275         /* ISC_LIST_INIT(rdata->list); */
276 }
277
278 #if 1
279 #define DNS_RDATA_INITIALIZED(rdata) \
280         ((rdata)->data == NULL && (rdata)->length == 0 && \
281          (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \
282          !ISC_LINK_LINKED((rdata), link))
283 #else
284 #ifdef ISC_LIST_CHECKINIT
285 #define DNS_RDATA_INITIALIZED(rdata) \
286         (!ISC_LINK_LINKED((rdata), link))
287 #else
288 #define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE
289 #endif
290 #endif
291
292 #define DNS_RDATA_VALIDFLAGS(rdata) \
293         (((rdata)->flags & ~(DNS_RDATA_UPDATE|DNS_RDATA_OFFLINE)) == 0)
294
295 void
296 dns_rdata_reset(dns_rdata_t *rdata) {
297
298         REQUIRE(rdata != NULL);
299
300         REQUIRE(!ISC_LINK_LINKED(rdata, link));
301         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
302
303         rdata->data = NULL;
304         rdata->length = 0;
305         rdata->rdclass = 0;
306         rdata->type = 0;
307         rdata->flags = 0;
308 }
309
310 /***
311  ***
312  ***/
313
314 void
315 dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
316
317         REQUIRE(src != NULL);
318         REQUIRE(target != NULL);
319
320         REQUIRE(DNS_RDATA_INITIALIZED(target));
321
322         REQUIRE(DNS_RDATA_VALIDFLAGS(src));
323         REQUIRE(DNS_RDATA_VALIDFLAGS(target));
324
325         target->data = src->data;
326         target->length = src->length;
327         target->rdclass = src->rdclass;
328         target->type = src->type;
329         target->flags = src->flags;
330 }
331
332
333 /***
334  *** Comparisons
335  ***/
336
337 int
338 dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
339         int result = 0;
340         isc_boolean_t use_default = ISC_FALSE;
341
342         REQUIRE(rdata1 != NULL);
343         REQUIRE(rdata2 != NULL);
344         REQUIRE(rdata1->data != NULL);
345         REQUIRE(rdata2->data != NULL);
346         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
347         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
348
349         if (rdata1->rdclass != rdata2->rdclass)
350                 return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
351
352         if (rdata1->type != rdata2->type)
353                 return (rdata1->type < rdata2->type ? -1 : 1);
354
355         COMPARESWITCH
356
357         if (use_default) {
358                 isc_region_t r1;
359                 isc_region_t r2;
360
361                 dns_rdata_toregion(rdata1, &r1);
362                 dns_rdata_toregion(rdata2, &r2);
363                 result = isc_region_compare(&r1, &r2);
364         }
365         return (result);
366 }
367
368 /***
369  *** Conversions
370  ***/
371
372 void
373 dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
374                      dns_rdatatype_t type, isc_region_t *r)
375 {
376
377         REQUIRE(rdata != NULL);
378         REQUIRE(DNS_RDATA_INITIALIZED(rdata));
379         REQUIRE(r != NULL);
380
381         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
382
383         rdata->data = r->base;
384         rdata->length = r->length;
385         rdata->rdclass = rdclass;
386         rdata->type = type;
387         rdata->flags = 0;
388 }
389
390 void
391 dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
392
393         REQUIRE(rdata != NULL);
394         REQUIRE(r != NULL);
395         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
396
397         r->base = rdata->data;
398         r->length = rdata->length;
399 }
400
401 isc_result_t
402 dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
403                    dns_rdatatype_t type, isc_buffer_t *source,
404                    dns_decompress_t *dctx, unsigned int options,
405                    isc_buffer_t *target)
406 {
407         isc_result_t result = ISC_R_NOTIMPLEMENTED;
408         isc_region_t region;
409         isc_buffer_t ss;
410         isc_buffer_t st;
411         isc_boolean_t use_default = ISC_FALSE;
412         isc_uint32_t activelength;
413
414         REQUIRE(dctx != NULL);
415         if (rdata != NULL) {
416                 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
417                 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
418         }
419
420         if (type == 0)
421                 return (DNS_R_FORMERR);
422
423         ss = *source;
424         st = *target;
425
426         activelength = isc_buffer_activelength(source);
427         INSIST(activelength < 65536);
428
429         FROMWIRESWITCH
430
431         if (use_default) {
432                 if (activelength > isc_buffer_availablelength(target))
433                         result = ISC_R_NOSPACE;
434                 else {
435                         isc_buffer_putmem(target, isc_buffer_current(source),
436                                           activelength);
437                         isc_buffer_forward(source, activelength);
438                         result = ISC_R_SUCCESS;
439                 }
440         }
441
442         /*
443          * We should have consumed all of our buffer.
444          */
445         if (result == ISC_R_SUCCESS && !buffer_empty(source))
446                 result = DNS_R_EXTRADATA;
447
448         if (rdata != NULL && result == ISC_R_SUCCESS) {
449                 region.base = isc_buffer_used(&st);
450                 region.length = isc_buffer_usedlength(target) -
451                                 isc_buffer_usedlength(&st);
452                 dns_rdata_fromregion(rdata, rdclass, type, &region);
453         }
454
455         if (result != ISC_R_SUCCESS) {
456                 *source = ss;
457                 *target = st;
458         }
459         return (result);
460 }
461
462 isc_result_t
463 dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
464                  isc_buffer_t *target)
465 {
466         isc_result_t result = ISC_R_NOTIMPLEMENTED;
467         isc_boolean_t use_default = ISC_FALSE;
468         isc_region_t tr;
469         isc_buffer_t st;
470
471         REQUIRE(rdata != NULL);
472         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
473
474         /*
475          * Some DynDNS meta-RRs have empty rdata.
476          */
477         if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
478                 INSIST(rdata->length == 0);
479                 return (ISC_R_SUCCESS);
480         }
481
482         st = *target;
483
484         TOWIRESWITCH
485
486         if (use_default) {
487                 isc_buffer_availableregion(target, &tr);
488                 if (tr.length < rdata->length)
489                         return (ISC_R_NOSPACE);
490                 memcpy(tr.base, rdata->data, rdata->length);
491                 isc_buffer_add(target, rdata->length);
492                 return (ISC_R_SUCCESS);
493         }
494         if (result != ISC_R_SUCCESS) {
495                 *target = st;
496                 INSIST(target->used < 65536);
497                 dns_compress_rollback(cctx, (isc_uint16_t)target->used);
498         }
499         return (result);
500 }
501
502 /*
503  * If the binary data in 'src' is valid uncompressed wire format
504  * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS
505  * and copy the validated rdata to 'dest'.  Otherwise return an error.
506  */
507 static isc_result_t
508 rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass,
509             dns_rdatatype_t type)
510 {
511         dns_decompress_t dctx;
512         dns_rdata_t rdata = DNS_RDATA_INIT;
513         isc_result_t result;
514
515         dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
516         isc_buffer_setactive(src, isc_buffer_usedlength(src));
517         result = dns_rdata_fromwire(&rdata, rdclass, type, src,
518                                     &dctx, 0, dest);
519         dns_decompress_invalidate(&dctx);
520
521         return (result);
522 }
523
524 static isc_result_t
525 unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type,
526                  isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target)
527 {
528         isc_result_t result;
529         isc_buffer_t *buf = NULL;
530         isc_token_t token;
531
532         if (type == 0 || dns_rdatatype_ismeta(type))
533                 return (DNS_R_METATYPE);
534
535         result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
536                                         ISC_FALSE);
537         if (result == ISC_R_SUCCESS && token.value.as_ulong > 65535U)
538                 return (ISC_R_RANGE);
539         result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong);
540         if (result != ISC_R_SUCCESS)
541                 return (result);
542
543         result = isc_hex_tobuffer(lexer, buf,
544                                   (unsigned int)token.value.as_ulong);
545         if (result != ISC_R_SUCCESS)
546                goto failure;
547         if (isc_buffer_usedlength(buf) != token.value.as_ulong) {
548                 result = ISC_R_UNEXPECTEDEND;
549                 goto failure;
550         }
551
552         if (dns_rdatatype_isknown(type)) {
553                 result = rdata_validate(buf, target, rdclass, type);
554         } else {
555                 isc_region_t r;
556                 isc_buffer_usedregion(buf, &r);
557                 result = isc_buffer_copyregion(target, &r);
558         }
559         if (result != ISC_R_SUCCESS)
560                 goto failure;
561
562         isc_buffer_free(&buf);
563         return (ISC_R_SUCCESS);
564
565  failure:
566         isc_buffer_free(&buf);
567         return (result);
568 }
569
570 isc_result_t
571 dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
572                    dns_rdatatype_t type, isc_lex_t *lexer,
573                    dns_name_t *origin, unsigned int options, isc_mem_t *mctx,
574                    isc_buffer_t *target, dns_rdatacallbacks_t *callbacks)
575 {
576         isc_result_t result = ISC_R_NOTIMPLEMENTED;
577         isc_region_t region;
578         isc_buffer_t st;
579         isc_token_t token;
580         unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
581                                   ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
582         char *name;
583         unsigned long line;
584         void (*callback)(dns_rdatacallbacks_t *, const char *, ...);
585         isc_result_t tresult;
586
587         REQUIRE(origin == NULL || dns_name_isabsolute(origin) == ISC_TRUE);
588         if (rdata != NULL) {
589                 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
590                 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
591         }
592         if (callbacks != NULL) {
593                 REQUIRE(callbacks->warn != NULL);
594                 REQUIRE(callbacks->error != NULL);
595         }
596
597         st = *target;
598
599         if (callbacks != NULL)
600                 callback = callbacks->error;
601         else
602                 callback = default_fromtext_callback;
603
604         result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
605                                         ISC_FALSE);
606         if (result != ISC_R_SUCCESS) {
607                 name = isc_lex_getsourcename(lexer);
608                 line = isc_lex_getsourceline(lexer);
609                 fromtext_error(callback, callbacks, name, line,
610                                &token, result);
611                 return (result);
612         }
613
614         if (strcmp(DNS_AS_STR(token), "\\#") == 0)
615                 result = unknown_fromtext(rdclass, type, lexer, mctx, target);
616         else {
617                 isc_lex_ungettoken(lexer, &token);
618
619                 FROMTEXTSWITCH
620         }
621
622         /*
623          * Consume to end of line / file.
624          * If not at end of line initially set error code.
625          * Call callback via fromtext_error once if there was an error.
626          */
627         do {
628                 name = isc_lex_getsourcename(lexer);
629                 line = isc_lex_getsourceline(lexer);
630                 tresult = isc_lex_gettoken(lexer, lexoptions, &token);
631                 if (tresult != ISC_R_SUCCESS) {
632                         if (result == ISC_R_SUCCESS)
633                                 result = tresult;
634                         if (callback != NULL)
635                                 fromtext_error(callback, callbacks, name,
636                                                line, NULL, result);
637                         break;
638                 } else if (token.type != isc_tokentype_eol &&
639                            token.type != isc_tokentype_eof) {
640                         if (result == ISC_R_SUCCESS)
641                                 result = DNS_R_EXTRATOKEN;
642                         if (callback != NULL) {
643                                 fromtext_error(callback, callbacks, name,
644                                                line, &token, result);
645                                 callback = NULL;
646                         }
647                 } else if (result != ISC_R_SUCCESS && callback != NULL) {
648                         fromtext_error(callback, callbacks, name, line,
649                                        &token, result);
650                         break;
651                 } else {
652                         if (token.type == isc_tokentype_eof)
653                                 fromtext_warneof(lexer, callbacks);
654                         break;
655                 }
656         } while (1);
657
658         if (rdata != NULL && result == ISC_R_SUCCESS) {
659                 region.base = isc_buffer_used(&st);
660                 region.length = isc_buffer_usedlength(target) -
661                                 isc_buffer_usedlength(&st);
662                 dns_rdata_fromregion(rdata, rdclass, type, &region);
663         }
664         if (result != ISC_R_SUCCESS) {
665                 *target = st;
666         }
667         return (result);
668 }
669
670 static isc_result_t
671 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
672              isc_buffer_t *target)
673 {
674         isc_result_t result = ISC_R_NOTIMPLEMENTED;
675         isc_boolean_t use_default = ISC_FALSE;
676         char buf[sizeof("65535")];
677         isc_region_t sr;
678
679         REQUIRE(rdata != NULL);
680         REQUIRE(tctx->origin == NULL ||
681                 dns_name_isabsolute(tctx->origin) == ISC_TRUE);
682
683         /*
684          * Some DynDNS meta-RRs have empty rdata.
685          */
686         if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
687                 INSIST(rdata->length == 0);
688                 return (ISC_R_SUCCESS);
689         }
690
691         TOTEXTSWITCH
692
693         if (use_default) {
694                 strlcpy(buf, "\\# ", sizeof(buf));
695                 result = str_totext(buf, target);
696                 dns_rdata_toregion(rdata, &sr);
697                 INSIST(sr.length < 65536);
698                 snprintf(buf, sizeof(buf), "%u", sr.length);
699                 result = str_totext(buf, target);
700                 if (sr.length != 0 && result == ISC_R_SUCCESS) {
701                         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
702                                 result = str_totext(" ( ", target);
703                         else
704                                 result = str_totext(" ", target);
705                         if (result == ISC_R_SUCCESS)
706                                 result = isc_hex_totext(&sr, tctx->width - 2,
707                                                         tctx->linebreak,
708                                                         target);
709                         if (result == ISC_R_SUCCESS &&
710                             (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
711                                 result = str_totext(" )", target);
712                 }
713         }
714
715         return (result);
716 }
717
718 isc_result_t
719 dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
720 {
721         dns_rdata_textctx_t tctx;
722
723         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
724
725         /*
726          * Set up formatting options for single-line output.
727          */
728         tctx.origin = origin;
729         tctx.flags = 0;
730         tctx.width = 60;
731         tctx.linebreak = " ";
732         return (rdata_totext(rdata, &tctx, target));
733 }
734
735 isc_result_t
736 dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
737                     unsigned int flags, unsigned int width,
738                     const char *linebreak, isc_buffer_t *target)
739 {
740         dns_rdata_textctx_t tctx;
741
742         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
743
744         /*
745          * Set up formatting options for formatted output.
746          */
747         tctx.origin = origin;
748         tctx.flags = flags;
749         if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) {
750                 tctx.width = width;
751                 tctx.linebreak = linebreak;
752         } else {
753                 tctx.width = 60; /* Used for hex word length only. */
754                 tctx.linebreak = " ";
755         }
756         return (rdata_totext(rdata, &tctx, target));
757 }
758
759 isc_result_t
760 dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
761                      dns_rdatatype_t type, void *source,
762                      isc_buffer_t *target)
763 {
764         isc_result_t result = ISC_R_NOTIMPLEMENTED;
765         isc_buffer_t st;
766         isc_region_t region;
767         isc_boolean_t use_default = ISC_FALSE;
768
769         REQUIRE(source != NULL);
770         if (rdata != NULL) {
771                 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
772                 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
773         }
774
775         st = *target;
776
777         FROMSTRUCTSWITCH
778
779         if (use_default)
780                 (void)NULL;
781
782         if (rdata != NULL && result == ISC_R_SUCCESS) {
783                 region.base = isc_buffer_used(&st);
784                 region.length = isc_buffer_usedlength(target) -
785                                 isc_buffer_usedlength(&st);
786                 dns_rdata_fromregion(rdata, rdclass, type, &region);
787         }
788         if (result != ISC_R_SUCCESS)
789                 *target = st;
790         return (result);
791 }
792
793 isc_result_t
794 dns_rdata_tostruct(dns_rdata_t *rdata, void *target, isc_mem_t *mctx) {
795         isc_result_t result = ISC_R_NOTIMPLEMENTED;
796         isc_boolean_t use_default = ISC_FALSE;
797
798         REQUIRE(rdata != NULL);
799         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
800
801         TOSTRUCTSWITCH
802
803         if (use_default)
804                 (void)NULL;
805
806         return (result);
807 }
808
809 void
810 dns_rdata_freestruct(void *source) {
811         dns_rdatacommon_t *common = source;
812         REQUIRE(source != NULL);
813
814         FREESTRUCTSWITCH
815 }
816
817 isc_result_t
818 dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
819                          void *arg)
820 {
821         isc_result_t result = ISC_R_NOTIMPLEMENTED;
822         isc_boolean_t use_default = ISC_FALSE;
823
824         /*
825          * Call 'add' for each name and type from 'rdata' which is subject to
826          * additional section processing.
827          */
828
829         REQUIRE(rdata != NULL);
830         REQUIRE(add != NULL);
831         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
832
833         ADDITIONALDATASWITCH
834
835         /* No additional processing for unknown types */
836         if (use_default)
837                 result = ISC_R_SUCCESS;
838
839         return (result);
840 }
841
842 isc_result_t
843 dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) {
844         isc_result_t result = ISC_R_NOTIMPLEMENTED;
845         isc_boolean_t use_default = ISC_FALSE;
846         isc_region_t r;
847
848         /*
849          * Send 'rdata' in DNSSEC canonical form to 'digest'.
850          */
851
852         REQUIRE(rdata != NULL);
853         REQUIRE(digest != NULL);
854         REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
855
856         DIGESTSWITCH
857
858         if (use_default) {
859                 dns_rdata_toregion(rdata, &r);
860                 result = (digest)(arg, &r);
861         }
862
863         return (result);
864 }
865
866 isc_boolean_t
867 dns_rdata_checkowner(dns_name_t *name, dns_rdataclass_t rdclass,
868                      dns_rdatatype_t type, isc_boolean_t wildcard)
869 {
870         isc_boolean_t result;
871
872         CHECKOWNERSWITCH
873         return (result);
874 }
875
876 isc_boolean_t
877 dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad)
878 {
879         isc_boolean_t result;
880
881         CHECKNAMESSWITCH
882         return (result);
883 }
884
885 unsigned int
886 dns_rdatatype_attributes(dns_rdatatype_t type)
887 {
888         RDATATYPE_ATTRIBUTE_SW
889         if (type >= (dns_rdatatype_t)128 && type < (dns_rdatatype_t)255)
890                 return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META);
891         return (DNS_RDATATYPEATTR_UNKNOWN);
892 }
893
894 isc_result_t
895 dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
896         unsigned int hash;
897         unsigned int n;
898         unsigned char a, b;
899
900         n = source->length;
901
902         if (n == 0)
903                 return (DNS_R_UNKNOWN);
904
905         a = tolower((unsigned char)source->base[0]);
906         b = tolower((unsigned char)source->base[n - 1]);
907
908         hash = ((a + n) * b) % 256;
909
910         /*
911          * This switch block is inlined via \#define, and will use "return"
912          * to return a result to the caller if it is a valid (known)
913          * rdatatype name.
914          */
915         RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep);
916
917         if (source->length > 4 && source->length < (4 + sizeof("65000")) &&
918             strncasecmp("type", source->base, 4) == 0) {
919                 char buf[sizeof("65000")];
920                 char *endp;
921                 unsigned int val;
922
923                 strncpy(buf, source->base + 4, source->length - 4);
924                 buf[source->length - 4] = '\0';
925                 val = strtoul(buf, &endp, 10);
926                 if (*endp == '\0' && val <= 0xffff) {
927                         *typep = (dns_rdatatype_t)val;
928                         return (ISC_R_SUCCESS);
929                 }
930         }
931
932         return (DNS_R_UNKNOWN);
933 }
934
935 isc_result_t
936 dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
937         char buf[sizeof("TYPE65535")];
938
939         RDATATYPE_TOTEXT_SW
940         snprintf(buf, sizeof(buf), "TYPE%u", type);
941         return (str_totext(buf, target));
942 }
943
944 void
945 dns_rdatatype_format(dns_rdatatype_t rdtype,
946                      char *array, unsigned int size)
947 {
948         isc_result_t result;
949         isc_buffer_t buf;
950
951         isc_buffer_init(&buf, array, size);
952         result = dns_rdatatype_totext(rdtype, &buf);
953         /*
954          * Null terminate.
955          */
956         if (result == ISC_R_SUCCESS) {
957                 if (isc_buffer_availablelength(&buf) >= 1)
958                         isc_buffer_putuint8(&buf, 0);
959                 else
960                         result = ISC_R_NOSPACE;
961         }
962         if (result != ISC_R_SUCCESS) {
963                 snprintf(array, size, "<unknown>");
964                 array[size - 1] = '\0';
965         }
966 }
967
968 /*
969  * Private function.
970  */
971
972 static unsigned int
973 name_length(dns_name_t *name) {
974         return (name->length);
975 }
976
977 static isc_result_t
978 txt_totext(isc_region_t *source, isc_buffer_t *target) {
979         unsigned int tl;
980         unsigned int n;
981         unsigned char *sp;
982         char *tp;
983         isc_region_t region;
984
985         isc_buffer_availableregion(target, &region);
986         sp = source->base;
987         tp = (char *)region.base;
988         tl = region.length;
989
990         n = *sp++;
991
992         REQUIRE(n + 1 <= source->length);
993
994         if (tl < 1)
995                 return (ISC_R_NOSPACE);
996         *tp++ = '"';
997         tl--;
998         while (n--) {
999                 if (*sp < 0x20 || *sp >= 0x7f) {
1000                         if (tl < 4)
1001                                 return (ISC_R_NOSPACE);
1002                         *tp++ = 0x5c;
1003                         *tp++ = 0x30 + ((*sp / 100) % 10);
1004                         *tp++ = 0x30 + ((*sp / 10) % 10);
1005                         *tp++ = 0x30 + (*sp % 10);
1006                         sp++;
1007                         tl -= 4;
1008                         continue;
1009                 }
1010                 /* double quote, semi-colon, backslash */
1011                 if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) {
1012                         if (tl < 2)
1013                                 return (ISC_R_NOSPACE);
1014                         *tp++ = '\\';
1015                         tl--;
1016                 }
1017                 if (tl < 1)
1018                         return (ISC_R_NOSPACE);
1019                 *tp++ = *sp++;
1020                 tl--;
1021         }
1022         if (tl < 1)
1023                 return (ISC_R_NOSPACE);
1024         *tp++ = '"';
1025         tl--;
1026         isc_buffer_add(target, tp - (char *)region.base);
1027         isc_region_consume(source, *source->base + 1);
1028         return (ISC_R_SUCCESS);
1029 }
1030
1031 static isc_result_t
1032 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
1033         isc_region_t tregion;
1034         isc_boolean_t escape;
1035         unsigned int n, nrem;
1036         char *s;
1037         unsigned char *t;
1038         int d;
1039         int c;
1040
1041         isc_buffer_availableregion(target, &tregion);
1042         s = source->base;
1043         n = source->length;
1044         t = tregion.base;
1045         nrem = tregion.length;
1046         escape = ISC_FALSE;
1047         if (nrem < 1)
1048                 return (ISC_R_NOSPACE);
1049         /*
1050          * Length byte.
1051          */
1052         nrem--;
1053         t++;
1054         /*
1055          * Maximum text string length.
1056          */
1057         if (nrem > 255)
1058                 nrem = 255;
1059         while (n-- != 0) {
1060                 c = (*s++) & 0xff;
1061                 if (escape && (d = decvalue((char)c)) != -1) {
1062                         c = d;
1063                         if (n == 0)
1064                                 return (DNS_R_SYNTAX);
1065                         n--;
1066                         if ((d = decvalue(*s++)) != -1)
1067                                 c = c * 10 + d;
1068                         else
1069                                 return (DNS_R_SYNTAX);
1070                         if (n == 0)
1071                                 return (DNS_R_SYNTAX);
1072                         n--;
1073                         if ((d = decvalue(*s++)) != -1)
1074                                 c = c * 10 + d;
1075                         else
1076                                 return (DNS_R_SYNTAX);
1077                         if (c > 255)
1078                                 return (DNS_R_SYNTAX);
1079                 } else if (!escape && c == '\\') {
1080                         escape = ISC_TRUE;
1081                         continue;
1082                 }
1083                 escape = ISC_FALSE;
1084                 if (nrem == 0)
1085                         return (ISC_R_NOSPACE);
1086                 *t++ = c;
1087                 nrem--;
1088         }
1089         if (escape)
1090                 return (DNS_R_SYNTAX);
1091         *tregion.base = t - tregion.base - 1;
1092         isc_buffer_add(target, *tregion.base + 1);
1093         return (ISC_R_SUCCESS);
1094 }
1095
1096 static isc_result_t
1097 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
1098         unsigned int n;
1099         isc_region_t sregion;
1100         isc_region_t tregion;
1101
1102         isc_buffer_activeregion(source, &sregion);
1103         if (sregion.length == 0)
1104                 return(ISC_R_UNEXPECTEDEND);
1105         n = *sregion.base + 1;
1106         if (n > sregion.length)
1107                 return (ISC_R_UNEXPECTEDEND);
1108
1109         isc_buffer_availableregion(target, &tregion);
1110         if (n > tregion.length)
1111                 return (ISC_R_NOSPACE);
1112
1113         memcpy(tregion.base, sregion.base, n);
1114         isc_buffer_forward(source, n);
1115         isc_buffer_add(target, n);
1116         return (ISC_R_SUCCESS);
1117 }
1118
1119 static isc_boolean_t
1120 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) {
1121         int l1, l2;
1122
1123         if (origin == NULL)
1124                 goto return_false;
1125
1126         if (dns_name_compare(origin, dns_rootname) == 0)
1127                 goto return_false;
1128
1129         if (!dns_name_issubdomain(name, origin))
1130                 goto return_false;
1131
1132         l1 = dns_name_countlabels(name);
1133         l2 = dns_name_countlabels(origin);
1134
1135         if (l1 == l2)
1136                 goto return_false;
1137
1138         /* Master files should be case preserving. */
1139         dns_name_getlabelsequence(name, l1 - l2, l2, target);
1140         if (!dns_name_caseequal(origin, target))
1141                 goto return_false;
1142
1143         dns_name_getlabelsequence(name, 0, l1 - l2, target);
1144         return (ISC_TRUE);
1145
1146 return_false:
1147         *target = *name;
1148         return (ISC_FALSE);
1149 }
1150
1151 static isc_result_t
1152 str_totext(const char *source, isc_buffer_t *target) {
1153         unsigned int l;
1154         isc_region_t region;
1155
1156         isc_buffer_availableregion(target, &region);
1157         l = strlen(source);
1158
1159         if (l > region.length)
1160                 return (ISC_R_NOSPACE);
1161
1162         memcpy(region.base, source, l);
1163         isc_buffer_add(target, l);
1164         return (ISC_R_SUCCESS);
1165 }
1166
1167 static isc_result_t
1168 inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
1169         char tmpbuf[64];
1170
1171         /* Note - inet_ntop doesn't do size checking on its input. */
1172         if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
1173                 return (ISC_R_NOSPACE);
1174         if (strlen(tmpbuf) > isc_buffer_availablelength(target))
1175                 return (ISC_R_NOSPACE);
1176         isc_buffer_putstr(target, tmpbuf);
1177         return (ISC_R_SUCCESS);
1178 }
1179
1180 static isc_boolean_t
1181 buffer_empty(isc_buffer_t *source) {
1182         return((source->current == source->active) ? ISC_TRUE : ISC_FALSE);
1183 }
1184
1185 static void
1186 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) {
1187         isc_buffer_init(buffer, region->base, region->length);
1188         isc_buffer_add(buffer, region->length);
1189         isc_buffer_setactive(buffer, region->length);
1190 }
1191
1192 static isc_result_t
1193 uint32_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1194         isc_region_t region;
1195
1196         isc_buffer_availableregion(target, &region);
1197         if (region.length < 4)
1198                 return (ISC_R_NOSPACE);
1199         isc_buffer_putuint32(target, value);
1200         return (ISC_R_SUCCESS);
1201 }
1202
1203 static isc_result_t
1204 uint16_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1205         isc_region_t region;
1206
1207         if (value > 0xffff)
1208                 return (ISC_R_RANGE);
1209         isc_buffer_availableregion(target, &region);
1210         if (region.length < 2)
1211                 return (ISC_R_NOSPACE);
1212         isc_buffer_putuint16(target, (isc_uint16_t)value);
1213         return (ISC_R_SUCCESS);
1214 }
1215
1216 static isc_result_t
1217 uint8_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1218         isc_region_t region;
1219
1220         if (value > 0xff)
1221                 return (ISC_R_RANGE);
1222         isc_buffer_availableregion(target, &region);
1223         if (region.length < 1)
1224                 return (ISC_R_NOSPACE);
1225         isc_buffer_putuint8(target, (isc_uint8_t)value);
1226         return (ISC_R_SUCCESS);
1227 }
1228
1229 static isc_result_t
1230 name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
1231         isc_region_t r;
1232         dns_name_toregion(name, &r);
1233         return (isc_buffer_copyregion(target, &r));
1234 }
1235
1236 static isc_uint32_t
1237 uint32_fromregion(isc_region_t *region) {
1238         isc_uint32_t value;
1239
1240         REQUIRE(region->length >= 4);
1241         value = region->base[0] << 24;
1242         value |= region->base[1] << 16;
1243         value |= region->base[2] << 8;
1244         value |= region->base[3];
1245         return(value);
1246 }
1247
1248 static isc_uint16_t
1249 uint16_consume_fromregion(isc_region_t *region) {
1250         isc_uint16_t r = uint16_fromregion(region);
1251
1252         isc_region_consume(region, 2);
1253         return r;
1254 }
1255
1256 static isc_uint16_t
1257 uint16_fromregion(isc_region_t *region) {
1258
1259         REQUIRE(region->length >= 2);
1260
1261         return ((region->base[0] << 8) | region->base[1]);
1262 }
1263
1264 static isc_uint8_t
1265 uint8_fromregion(isc_region_t *region) {
1266
1267         REQUIRE(region->length >= 1);
1268
1269         return (region->base[0]);
1270 }
1271
1272 static isc_uint8_t
1273 uint8_consume_fromregion(isc_region_t *region) {
1274         isc_uint8_t r = uint8_fromregion(region);
1275
1276         isc_region_consume(region, 1);
1277         return r;
1278 }
1279
1280 static isc_result_t
1281 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
1282         isc_region_t tr;
1283
1284         isc_buffer_availableregion(target, &tr);
1285         if (length > tr.length)
1286                 return (ISC_R_NOSPACE);
1287         memcpy(tr.base, base, length);
1288         isc_buffer_add(target, length);
1289         return (ISC_R_SUCCESS);
1290 }
1291
1292 static int
1293 hexvalue(char value) {
1294         char *s;
1295         unsigned char c;
1296
1297         c = (unsigned char)value;
1298
1299         if (!isascii(c))
1300                 return (-1);
1301         if (isupper(c))
1302                 c = tolower(c);
1303         if ((s = strchr(hexdigits, c)) == NULL)
1304                 return (-1);
1305         return (s - hexdigits);
1306 }
1307
1308 static int
1309 decvalue(char value) {
1310         char *s;
1311
1312         /*
1313          * isascii() is valid for full range of int values, no need to
1314          * mask or cast.
1315          */
1316         if (!isascii(value))
1317                 return (-1);
1318         if ((s = strchr(decdigits, value)) == NULL)
1319                 return (-1);
1320         return (s - decdigits);
1321 }
1322
1323 static const char atob_digits[86] =
1324         "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
1325         "abcdefghijklmnopqrstu";
1326 /*
1327  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
1328  * Computes the number of bytes, and three kinds of simple checksums.
1329  * Incoming bytes are collected into 32-bit words, then printed in base 85:
1330  *      exp(85,5) > exp(2,32)
1331  * The ASCII characters used are between '!' and 'u';
1332  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
1333  *
1334  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
1335  * the atob/btoa programs, released with the compress program, in mod.sources.
1336  * Modified by Mike Schwartz 8/19/86 for use in BIND.
1337  * Modified to be re-entrant 3/2/99.
1338  */
1339
1340
1341 struct state {
1342         isc_int32_t Ceor;
1343         isc_int32_t Csum;
1344         isc_int32_t Crot;
1345         isc_int32_t word;
1346         isc_int32_t bcount;
1347 };
1348
1349 #define Ceor state->Ceor
1350 #define Csum state->Csum
1351 #define Crot state->Crot
1352 #define word state->word
1353 #define bcount state->bcount
1354
1355 #define times85(x)      ((((((x<<2)+x)<<2)+x)<<2)+x)
1356
1357 static isc_result_t     byte_atob(int c, isc_buffer_t *target,
1358                                   struct state *state);
1359 static isc_result_t     putbyte(int c, isc_buffer_t *, struct state *state);
1360 static isc_result_t     byte_btoa(int c, isc_buffer_t *, struct state *state);
1361
1362 /*
1363  * Decode ASCII-encoded byte c into binary representation and
1364  * place into *bufp, advancing bufp.
1365  */
1366 static isc_result_t
1367 byte_atob(int c, isc_buffer_t *target, struct state *state) {
1368         char *s;
1369         if (c == 'z') {
1370                 if (bcount != 0)
1371                         return(DNS_R_SYNTAX);
1372                 else {
1373                         RETERR(putbyte(0, target, state));
1374                         RETERR(putbyte(0, target, state));
1375                         RETERR(putbyte(0, target, state));
1376                         RETERR(putbyte(0, target, state));
1377                 }
1378         } else if ((s = strchr(atob_digits, c)) != NULL) {
1379                 if (bcount == 0) {
1380                         word = s - atob_digits;
1381                         ++bcount;
1382                 } else if (bcount < 4) {
1383                         word = times85(word);
1384                         word += s - atob_digits;
1385                         ++bcount;
1386                 } else {
1387                         word = times85(word);
1388                         word += s - atob_digits;
1389                         RETERR(putbyte((word >> 24) & 0xff, target, state));
1390                         RETERR(putbyte((word >> 16) & 0xff, target, state));
1391                         RETERR(putbyte((word >> 8) & 0xff, target, state));
1392                         RETERR(putbyte(word & 0xff, target, state));
1393                         word = 0;
1394                         bcount = 0;
1395                 }
1396         } else
1397                 return(DNS_R_SYNTAX);
1398         return(ISC_R_SUCCESS);
1399 }
1400
1401 /*
1402  * Compute checksum info and place c into target.
1403  */
1404 static isc_result_t
1405 putbyte(int c, isc_buffer_t *target, struct state *state) {
1406         isc_region_t tr;
1407
1408         Ceor ^= c;
1409         Csum += c;
1410         Csum += 1;
1411         if ((Crot & 0x80000000)) {
1412                 Crot <<= 1;
1413                 Crot += 1;
1414         } else {
1415                 Crot <<= 1;
1416         }
1417         Crot += c;
1418         isc_buffer_availableregion(target, &tr);
1419         if (tr.length < 1)
1420                 return (ISC_R_NOSPACE);
1421         tr.base[0] = c;
1422         isc_buffer_add(target, 1);
1423         return (ISC_R_SUCCESS);
1424 }
1425
1426 /*
1427  * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
1428  * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
1429  * outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
1430  * in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
1431  * boundary, there will be no problem...it will be padded with 0 bytes, and
1432  * numbytes will indicate the correct number of bytes.  The main point is
1433  * that since the buffer is filled in 4 bytes at a time, even if there is
1434  * not a full 4 bytes of data at the end, there has to be room to 0-pad the
1435  * data, so the buffer must be of size divisible by 4).  Place the number of
1436  * output bytes in numbytes, and return a failure/success status.
1437  */
1438
1439 static isc_result_t
1440 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) {
1441         long oeor, osum, orot;
1442         struct state statebuf, *state= &statebuf;
1443         isc_token_t token;
1444         char c;
1445         char *e;
1446
1447         Ceor = Csum = Crot = word = bcount = 0;
1448
1449         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1450                                       ISC_FALSE));
1451         while (token.value.as_textregion.length != 0) {
1452                 if ((c = token.value.as_textregion.base[0]) == 'x') {
1453                         break;
1454                 } else
1455                         RETERR(byte_atob(c, target, state));
1456                 isc_textregion_consume(&token.value.as_textregion, 1);
1457         }
1458
1459         /*
1460          * Number of bytes.
1461          */
1462         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
1463                                       ISC_FALSE));
1464         if ((token.value.as_ulong % 4) != 0U)
1465                 isc_buffer_subtract(target,  4 - (token.value.as_ulong % 4));
1466
1467         /*
1468          * Checksum.
1469          */
1470         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1471                                       ISC_FALSE));
1472         oeor = strtol(DNS_AS_STR(token), &e, 16);
1473         if (*e != 0)
1474                 return (DNS_R_SYNTAX);
1475
1476         /*
1477          * Checksum.
1478          */
1479         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1480                                       ISC_FALSE));
1481         osum = strtol(DNS_AS_STR(token), &e, 16);
1482         if (*e != 0)
1483                 return (DNS_R_SYNTAX);
1484
1485         /*
1486          * Checksum.
1487          */
1488         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1489                                       ISC_FALSE));
1490         orot = strtol(DNS_AS_STR(token), &e, 16);
1491         if (*e != 0)
1492                 return (DNS_R_SYNTAX);
1493
1494         if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
1495                 return(DNS_R_BADCKSUM);
1496         return (ISC_R_SUCCESS);
1497 }
1498
1499 /*
1500  * Encode binary byte c into ASCII representation and place into *bufp,
1501  * advancing bufp.
1502  */
1503 static isc_result_t
1504 byte_btoa(int c, isc_buffer_t *target, struct state *state) {
1505         isc_region_t tr;
1506
1507         isc_buffer_availableregion(target, &tr);
1508         Ceor ^= c;
1509         Csum += c;
1510         Csum += 1;
1511         if ((Crot & 0x80000000)) {
1512                 Crot <<= 1;
1513                 Crot += 1;
1514         } else {
1515                 Crot <<= 1;
1516         }
1517         Crot += c;
1518
1519         word <<= 8;
1520         word |= c;
1521         if (bcount == 3) {
1522                 if (word == 0) {
1523                         if (tr.length < 1)
1524                                 return (ISC_R_NOSPACE);
1525                         tr.base[0] = 'z';
1526                         isc_buffer_add(target, 1);
1527                 } else {
1528                     register int tmp = 0;
1529                     register isc_int32_t tmpword = word;
1530
1531                     if (tmpword < 0) {
1532                            /*
1533                             * Because some don't support u_long.
1534                             */
1535                         tmp = 32;
1536                         tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1537                     }
1538                     if (tmpword < 0) {
1539                         tmp = 64;
1540                         tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1541                     }
1542                         if (tr.length < 5)
1543                                 return (ISC_R_NOSPACE);
1544                         tr.base[0] = atob_digits[(tmpword /
1545                                               (isc_int32_t)(85 * 85 * 85 * 85))
1546                                                 + tmp];
1547                         tmpword %= (isc_int32_t)(85 * 85 * 85 * 85);
1548                         tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
1549                         tmpword %= (85 * 85 * 85);
1550                         tr.base[2] = atob_digits[tmpword / (85 * 85)];
1551                         tmpword %= (85 * 85);
1552                         tr.base[3] = atob_digits[tmpword / 85];
1553                         tmpword %= 85;
1554                         tr.base[4] = atob_digits[tmpword];
1555                         isc_buffer_add(target, 5);
1556                 }
1557                 bcount = 0;
1558         } else {
1559                 bcount += 1;
1560         }
1561         return (ISC_R_SUCCESS);
1562 }
1563
1564
1565 /*
1566  * Encode the binary data from inbuf, of length inbuflen, into a
1567  * target.  Return success/failure status
1568  */
1569 static isc_result_t
1570 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
1571         int inc;
1572         struct state statebuf, *state = &statebuf;
1573         char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
1574
1575         Ceor = Csum = Crot = word = bcount = 0;
1576         for (inc = 0; inc < inbuflen; inbuf++, inc++)
1577                 RETERR(byte_btoa(*inbuf, target, state));
1578
1579         while (bcount != 0)
1580                 RETERR(byte_btoa(0, target, state));
1581
1582         /*
1583          * Put byte count and checksum information at end of buffer,
1584          * delimited by 'x'
1585          */
1586         snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
1587         return (str_totext(buf, target));
1588 }
1589
1590
1591 static void
1592 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt,
1593                           ...)
1594 {
1595         va_list ap;
1596
1597         UNUSED(callbacks);
1598
1599         va_start(ap, fmt);
1600         vfprintf(stderr, fmt, ap);
1601         va_end(ap);
1602         fprintf(stderr, "\n");
1603 }
1604
1605 static void
1606 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) {
1607         if (isc_lex_isfile(lexer) && callbacks != NULL) {
1608                 const char *name = isc_lex_getsourcename(lexer);
1609                 if (name == NULL)
1610                         name = "UNKNOWN";
1611                 (*callbacks->warn)(callbacks,
1612                                    "%s:%lu: file does not end with newline",
1613                                    name, isc_lex_getsourceline(lexer));
1614         }
1615 }
1616
1617 static void
1618 warn_badmx(isc_token_t *token, isc_lex_t *lexer,
1619            dns_rdatacallbacks_t *callbacks)
1620 {
1621         const char *file;
1622         unsigned long line;
1623
1624         if (lexer != NULL) {
1625                 file = isc_lex_getsourcename(lexer);
1626                 line = isc_lex_getsourceline(lexer);
1627                 (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
1628                                    file, line, DNS_AS_STR(*token),
1629                                    dns_result_totext(DNS_R_MXISADDRESS));
1630         }
1631 }
1632
1633 static void
1634 warn_badname(dns_name_t *name, isc_lex_t *lexer,
1635              dns_rdatacallbacks_t *callbacks)
1636 {
1637         const char *file;
1638         unsigned long line;
1639         char namebuf[DNS_NAME_FORMATSIZE];
1640
1641         if (lexer != NULL) {
1642                 file = isc_lex_getsourcename(lexer);
1643                 line = isc_lex_getsourceline(lexer);
1644                 dns_name_format(name, namebuf, sizeof(namebuf));
1645                 (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
1646                                    file, line, namebuf,
1647                                    dns_result_totext(DNS_R_BADNAME));
1648         }
1649 }
1650
1651 static void
1652 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
1653                dns_rdatacallbacks_t *callbacks, const char *name,
1654                unsigned long line, isc_token_t *token, isc_result_t result)
1655 {
1656         if (name == NULL)
1657                 name = "UNKNOWN";
1658
1659         if (token != NULL) {
1660                 switch (token->type) {
1661                 case isc_tokentype_eol:
1662                         (*callback)(callbacks, "%s: %s:%lu: near eol: %s",
1663                                     "dns_rdata_fromtext", name, line,
1664                                     dns_result_totext(result));
1665                         break;
1666                 case isc_tokentype_eof:
1667                         (*callback)(callbacks, "%s: %s:%lu: near eof: %s",
1668                                     "dns_rdata_fromtext", name, line,
1669                                     dns_result_totext(result));
1670                         break;
1671                 case isc_tokentype_number:
1672                         (*callback)(callbacks, "%s: %s:%lu: near %lu: %s",
1673                                     "dns_rdata_fromtext", name, line,
1674                                     token->value.as_ulong,
1675                                     dns_result_totext(result));
1676                         break;
1677                 case isc_tokentype_string:
1678                 case isc_tokentype_qstring:
1679                         (*callback)(callbacks, "%s: %s:%lu: near '%s': %s",
1680                                     "dns_rdata_fromtext", name, line,
1681                                     DNS_AS_STR(*token),
1682                                     dns_result_totext(result));
1683                         break;
1684                 default:
1685                         (*callback)(callbacks, "%s: %s:%lu: %s",
1686                                     "dns_rdata_fromtext", name, line,
1687                                     dns_result_totext(result));
1688                         break;
1689                 }
1690         } else {
1691                 (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s",
1692                             name, line, dns_result_totext(result));
1693         }
1694 }
1695
1696 dns_rdatatype_t
1697 dns_rdata_covers(dns_rdata_t *rdata) {
1698         if (rdata->type == 46)
1699                 return (covers_rrsig(rdata));
1700         return (covers_sig(rdata));
1701 }
1702
1703 isc_boolean_t
1704 dns_rdatatype_ismeta(dns_rdatatype_t type) {
1705         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0)
1706                 return (ISC_TRUE);
1707         return (ISC_FALSE);
1708 }
1709
1710 isc_boolean_t
1711 dns_rdatatype_issingleton(dns_rdatatype_t type) {
1712         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON)
1713             != 0)
1714                 return (ISC_TRUE);
1715         return (ISC_FALSE);
1716 }
1717
1718 isc_boolean_t
1719 dns_rdatatype_notquestion(dns_rdatatype_t type) {
1720         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION)
1721             != 0)
1722                 return (ISC_TRUE);
1723         return (ISC_FALSE);
1724 }
1725
1726 isc_boolean_t
1727 dns_rdatatype_questiononly(dns_rdatatype_t type) {
1728         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY)
1729             != 0)
1730                 return (ISC_TRUE);
1731         return (ISC_FALSE);
1732 }
1733
1734 isc_boolean_t
1735 dns_rdatatype_atparent(dns_rdatatype_t type) {
1736         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0)
1737                 return (ISC_TRUE);
1738         return (ISC_FALSE);
1739 }
1740
1741 isc_boolean_t
1742 dns_rdataclass_ismeta(dns_rdataclass_t rdclass) {
1743
1744         if (rdclass == dns_rdataclass_reserved0
1745             || rdclass == dns_rdataclass_none
1746             || rdclass == dns_rdataclass_any)
1747                 return (ISC_TRUE);
1748
1749         return (ISC_FALSE);  /* Assume it is not a meta class. */
1750 }
1751
1752 isc_boolean_t
1753 dns_rdatatype_isdnssec(dns_rdatatype_t type) {
1754         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0)
1755                 return (ISC_TRUE);
1756         return (ISC_FALSE);
1757 }
1758
1759 isc_boolean_t
1760 dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
1761         if ((dns_rdatatype_attributes(type)
1762              & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH))
1763             != 0)
1764                 return (ISC_TRUE);
1765         return (ISC_FALSE);
1766 }
1767
1768 isc_boolean_t
1769 dns_rdatatype_isknown(dns_rdatatype_t type) {
1770         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN)
1771             == 0)
1772                 return (ISC_TRUE);
1773         return (ISC_FALSE);
1774 }