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