]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/bind9/lib/dns/rdata.c
Fix a problem where zero-length RDATA fields can cause named(8) to crash.
[FreeBSD/releng/8.1.git] / contrib / bind9 / lib / dns / rdata.c
1 /*
2  * Copyright (C) 2004-2009  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.2 2009/02/16 23:47:15 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->length == 0 || rdata1->data != NULL);
345         REQUIRE(rdata2->length == 0 || 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         dns_name_getlabelsequence(name, 0, l1 - l2, target);
1139         return (ISC_TRUE);
1140
1141 return_false:
1142         *target = *name;
1143         return (ISC_FALSE);
1144 }
1145
1146 static isc_result_t
1147 str_totext(const char *source, isc_buffer_t *target) {
1148         unsigned int l;
1149         isc_region_t region;
1150
1151         isc_buffer_availableregion(target, &region);
1152         l = strlen(source);
1153
1154         if (l > region.length)
1155                 return (ISC_R_NOSPACE);
1156
1157         memcpy(region.base, source, l);
1158         isc_buffer_add(target, l);
1159         return (ISC_R_SUCCESS);
1160 }
1161
1162 static isc_result_t
1163 inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
1164         char tmpbuf[64];
1165
1166         /* Note - inet_ntop doesn't do size checking on its input. */
1167         if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
1168                 return (ISC_R_NOSPACE);
1169         if (strlen(tmpbuf) > isc_buffer_availablelength(target))
1170                 return (ISC_R_NOSPACE);
1171         isc_buffer_putstr(target, tmpbuf);
1172         return (ISC_R_SUCCESS);
1173 }
1174
1175 static isc_boolean_t
1176 buffer_empty(isc_buffer_t *source) {
1177         return((source->current == source->active) ? ISC_TRUE : ISC_FALSE);
1178 }
1179
1180 static void
1181 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) {
1182         isc_buffer_init(buffer, region->base, region->length);
1183         isc_buffer_add(buffer, region->length);
1184         isc_buffer_setactive(buffer, region->length);
1185 }
1186
1187 static isc_result_t
1188 uint32_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1189         isc_region_t region;
1190
1191         isc_buffer_availableregion(target, &region);
1192         if (region.length < 4)
1193                 return (ISC_R_NOSPACE);
1194         isc_buffer_putuint32(target, value);
1195         return (ISC_R_SUCCESS);
1196 }
1197
1198 static isc_result_t
1199 uint16_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1200         isc_region_t region;
1201
1202         if (value > 0xffff)
1203                 return (ISC_R_RANGE);
1204         isc_buffer_availableregion(target, &region);
1205         if (region.length < 2)
1206                 return (ISC_R_NOSPACE);
1207         isc_buffer_putuint16(target, (isc_uint16_t)value);
1208         return (ISC_R_SUCCESS);
1209 }
1210
1211 static isc_result_t
1212 uint8_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1213         isc_region_t region;
1214
1215         if (value > 0xff)
1216                 return (ISC_R_RANGE);
1217         isc_buffer_availableregion(target, &region);
1218         if (region.length < 1)
1219                 return (ISC_R_NOSPACE);
1220         isc_buffer_putuint8(target, (isc_uint8_t)value);
1221         return (ISC_R_SUCCESS);
1222 }
1223
1224 static isc_result_t
1225 name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
1226         isc_region_t r;
1227         dns_name_toregion(name, &r);
1228         return (isc_buffer_copyregion(target, &r));
1229 }
1230
1231 static isc_uint32_t
1232 uint32_fromregion(isc_region_t *region) {
1233         isc_uint32_t value;
1234
1235         REQUIRE(region->length >= 4);
1236         value = region->base[0] << 24;
1237         value |= region->base[1] << 16;
1238         value |= region->base[2] << 8;
1239         value |= region->base[3];
1240         return(value);
1241 }
1242
1243 static isc_uint16_t
1244 uint16_consume_fromregion(isc_region_t *region) {
1245         isc_uint16_t r = uint16_fromregion(region);
1246
1247         isc_region_consume(region, 2);
1248         return r;
1249 }
1250
1251 static isc_uint16_t
1252 uint16_fromregion(isc_region_t *region) {
1253
1254         REQUIRE(region->length >= 2);
1255
1256         return ((region->base[0] << 8) | region->base[1]);
1257 }
1258
1259 static isc_uint8_t
1260 uint8_fromregion(isc_region_t *region) {
1261
1262         REQUIRE(region->length >= 1);
1263
1264         return (region->base[0]);
1265 }
1266
1267 static isc_uint8_t
1268 uint8_consume_fromregion(isc_region_t *region) {
1269         isc_uint8_t r = uint8_fromregion(region);
1270
1271         isc_region_consume(region, 1);
1272         return r;
1273 }
1274
1275 static isc_result_t
1276 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
1277         isc_region_t tr;
1278
1279         isc_buffer_availableregion(target, &tr);
1280         if (length > tr.length)
1281                 return (ISC_R_NOSPACE);
1282         memcpy(tr.base, base, length);
1283         isc_buffer_add(target, length);
1284         return (ISC_R_SUCCESS);
1285 }
1286
1287 static int
1288 hexvalue(char value) {
1289         char *s;
1290         unsigned char c;
1291
1292         c = (unsigned char)value;
1293
1294         if (!isascii(c))
1295                 return (-1);
1296         if (isupper(c))
1297                 c = tolower(c);
1298         if ((s = strchr(hexdigits, c)) == NULL)
1299                 return (-1);
1300         return (s - hexdigits);
1301 }
1302
1303 static int
1304 decvalue(char value) {
1305         char *s;
1306
1307         /*
1308          * isascii() is valid for full range of int values, no need to
1309          * mask or cast.
1310          */
1311         if (!isascii(value))
1312                 return (-1);
1313         if ((s = strchr(decdigits, value)) == NULL)
1314                 return (-1);
1315         return (s - decdigits);
1316 }
1317
1318 static const char atob_digits[86] =
1319         "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
1320         "abcdefghijklmnopqrstu";
1321 /*
1322  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
1323  * Computes the number of bytes, and three kinds of simple checksums.
1324  * Incoming bytes are collected into 32-bit words, then printed in base 85:
1325  *      exp(85,5) > exp(2,32)
1326  * The ASCII characters used are between '!' and 'u';
1327  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
1328  *
1329  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
1330  * the atob/btoa programs, released with the compress program, in mod.sources.
1331  * Modified by Mike Schwartz 8/19/86 for use in BIND.
1332  * Modified to be re-entrant 3/2/99.
1333  */
1334
1335
1336 struct state {
1337         isc_int32_t Ceor;
1338         isc_int32_t Csum;
1339         isc_int32_t Crot;
1340         isc_int32_t word;
1341         isc_int32_t bcount;
1342 };
1343
1344 #define Ceor state->Ceor
1345 #define Csum state->Csum
1346 #define Crot state->Crot
1347 #define word state->word
1348 #define bcount state->bcount
1349
1350 #define times85(x)      ((((((x<<2)+x)<<2)+x)<<2)+x)
1351
1352 static isc_result_t     byte_atob(int c, isc_buffer_t *target,
1353                                   struct state *state);
1354 static isc_result_t     putbyte(int c, isc_buffer_t *, struct state *state);
1355 static isc_result_t     byte_btoa(int c, isc_buffer_t *, struct state *state);
1356
1357 /*
1358  * Decode ASCII-encoded byte c into binary representation and
1359  * place into *bufp, advancing bufp.
1360  */
1361 static isc_result_t
1362 byte_atob(int c, isc_buffer_t *target, struct state *state) {
1363         char *s;
1364         if (c == 'z') {
1365                 if (bcount != 0)
1366                         return(DNS_R_SYNTAX);
1367                 else {
1368                         RETERR(putbyte(0, target, state));
1369                         RETERR(putbyte(0, target, state));
1370                         RETERR(putbyte(0, target, state));
1371                         RETERR(putbyte(0, target, state));
1372                 }
1373         } else if ((s = strchr(atob_digits, c)) != NULL) {
1374                 if (bcount == 0) {
1375                         word = s - atob_digits;
1376                         ++bcount;
1377                 } else if (bcount < 4) {
1378                         word = times85(word);
1379                         word += s - atob_digits;
1380                         ++bcount;
1381                 } else {
1382                         word = times85(word);
1383                         word += s - atob_digits;
1384                         RETERR(putbyte((word >> 24) & 0xff, target, state));
1385                         RETERR(putbyte((word >> 16) & 0xff, target, state));
1386                         RETERR(putbyte((word >> 8) & 0xff, target, state));
1387                         RETERR(putbyte(word & 0xff, target, state));
1388                         word = 0;
1389                         bcount = 0;
1390                 }
1391         } else
1392                 return(DNS_R_SYNTAX);
1393         return(ISC_R_SUCCESS);
1394 }
1395
1396 /*
1397  * Compute checksum info and place c into target.
1398  */
1399 static isc_result_t
1400 putbyte(int c, isc_buffer_t *target, struct state *state) {
1401         isc_region_t tr;
1402
1403         Ceor ^= c;
1404         Csum += c;
1405         Csum += 1;
1406         if ((Crot & 0x80000000)) {
1407                 Crot <<= 1;
1408                 Crot += 1;
1409         } else {
1410                 Crot <<= 1;
1411         }
1412         Crot += c;
1413         isc_buffer_availableregion(target, &tr);
1414         if (tr.length < 1)
1415                 return (ISC_R_NOSPACE);
1416         tr.base[0] = c;
1417         isc_buffer_add(target, 1);
1418         return (ISC_R_SUCCESS);
1419 }
1420
1421 /*
1422  * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
1423  * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
1424  * outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
1425  * in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
1426  * boundary, there will be no problem...it will be padded with 0 bytes, and
1427  * numbytes will indicate the correct number of bytes.  The main point is
1428  * that since the buffer is filled in 4 bytes at a time, even if there is
1429  * not a full 4 bytes of data at the end, there has to be room to 0-pad the
1430  * data, so the buffer must be of size divisible by 4).  Place the number of
1431  * output bytes in numbytes, and return a failure/success status.
1432  */
1433
1434 static isc_result_t
1435 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) {
1436         long oeor, osum, orot;
1437         struct state statebuf, *state= &statebuf;
1438         isc_token_t token;
1439         char c;
1440         char *e;
1441
1442         Ceor = Csum = Crot = word = bcount = 0;
1443
1444         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1445                                       ISC_FALSE));
1446         while (token.value.as_textregion.length != 0) {
1447                 if ((c = token.value.as_textregion.base[0]) == 'x') {
1448                         break;
1449                 } else
1450                         RETERR(byte_atob(c, target, state));
1451                 isc_textregion_consume(&token.value.as_textregion, 1);
1452         }
1453
1454         /*
1455          * Number of bytes.
1456          */
1457         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
1458                                       ISC_FALSE));
1459         if ((token.value.as_ulong % 4) != 0U)
1460                 isc_buffer_subtract(target,  4 - (token.value.as_ulong % 4));
1461
1462         /*
1463          * Checksum.
1464          */
1465         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1466                                       ISC_FALSE));
1467         oeor = strtol(DNS_AS_STR(token), &e, 16);
1468         if (*e != 0)
1469                 return (DNS_R_SYNTAX);
1470
1471         /*
1472          * Checksum.
1473          */
1474         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1475                                       ISC_FALSE));
1476         osum = strtol(DNS_AS_STR(token), &e, 16);
1477         if (*e != 0)
1478                 return (DNS_R_SYNTAX);
1479
1480         /*
1481          * Checksum.
1482          */
1483         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1484                                       ISC_FALSE));
1485         orot = strtol(DNS_AS_STR(token), &e, 16);
1486         if (*e != 0)
1487                 return (DNS_R_SYNTAX);
1488
1489         if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
1490                 return(DNS_R_BADCKSUM);
1491         return (ISC_R_SUCCESS);
1492 }
1493
1494 /*
1495  * Encode binary byte c into ASCII representation and place into *bufp,
1496  * advancing bufp.
1497  */
1498 static isc_result_t
1499 byte_btoa(int c, isc_buffer_t *target, struct state *state) {
1500         isc_region_t tr;
1501
1502         isc_buffer_availableregion(target, &tr);
1503         Ceor ^= c;
1504         Csum += c;
1505         Csum += 1;
1506         if ((Crot & 0x80000000)) {
1507                 Crot <<= 1;
1508                 Crot += 1;
1509         } else {
1510                 Crot <<= 1;
1511         }
1512         Crot += c;
1513
1514         word <<= 8;
1515         word |= c;
1516         if (bcount == 3) {
1517                 if (word == 0) {
1518                         if (tr.length < 1)
1519                                 return (ISC_R_NOSPACE);
1520                         tr.base[0] = 'z';
1521                         isc_buffer_add(target, 1);
1522                 } else {
1523                     register int tmp = 0;
1524                     register isc_int32_t tmpword = word;
1525
1526                     if (tmpword < 0) {
1527                            /*
1528                             * Because some don't support u_long.
1529                             */
1530                         tmp = 32;
1531                         tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1532                     }
1533                     if (tmpword < 0) {
1534                         tmp = 64;
1535                         tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1536                     }
1537                         if (tr.length < 5)
1538                                 return (ISC_R_NOSPACE);
1539                         tr.base[0] = atob_digits[(tmpword /
1540                                               (isc_int32_t)(85 * 85 * 85 * 85))
1541                                                 + tmp];
1542                         tmpword %= (isc_int32_t)(85 * 85 * 85 * 85);
1543                         tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
1544                         tmpword %= (85 * 85 * 85);
1545                         tr.base[2] = atob_digits[tmpword / (85 * 85)];
1546                         tmpword %= (85 * 85);
1547                         tr.base[3] = atob_digits[tmpword / 85];
1548                         tmpword %= 85;
1549                         tr.base[4] = atob_digits[tmpword];
1550                         isc_buffer_add(target, 5);
1551                 }
1552                 bcount = 0;
1553         } else {
1554                 bcount += 1;
1555         }
1556         return (ISC_R_SUCCESS);
1557 }
1558
1559
1560 /*
1561  * Encode the binary data from inbuf, of length inbuflen, into a
1562  * target.  Return success/failure status
1563  */
1564 static isc_result_t
1565 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
1566         int inc;
1567         struct state statebuf, *state = &statebuf;
1568         char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
1569
1570         Ceor = Csum = Crot = word = bcount = 0;
1571         for (inc = 0; inc < inbuflen; inbuf++, inc++)
1572                 RETERR(byte_btoa(*inbuf, target, state));
1573
1574         while (bcount != 0)
1575                 RETERR(byte_btoa(0, target, state));
1576
1577         /*
1578          * Put byte count and checksum information at end of buffer,
1579          * delimited by 'x'
1580          */
1581         snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
1582         return (str_totext(buf, target));
1583 }
1584
1585
1586 static void
1587 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt,
1588                           ...)
1589 {
1590         va_list ap;
1591
1592         UNUSED(callbacks);
1593
1594         va_start(ap, fmt);
1595         vfprintf(stderr, fmt, ap);
1596         va_end(ap);
1597         fprintf(stderr, "\n");
1598 }
1599
1600 static void
1601 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) {
1602         if (isc_lex_isfile(lexer) && callbacks != NULL) {
1603                 const char *name = isc_lex_getsourcename(lexer);
1604                 if (name == NULL)
1605                         name = "UNKNOWN";
1606                 (*callbacks->warn)(callbacks,
1607                                    "%s:%lu: file does not end with newline",
1608                                    name, isc_lex_getsourceline(lexer));
1609         }
1610 }
1611
1612 static void
1613 warn_badmx(isc_token_t *token, isc_lex_t *lexer,
1614            dns_rdatacallbacks_t *callbacks)
1615 {
1616         const char *file;
1617         unsigned long line;
1618
1619         if (lexer != NULL) {
1620                 file = isc_lex_getsourcename(lexer);
1621                 line = isc_lex_getsourceline(lexer);
1622                 (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
1623                                    file, line, DNS_AS_STR(*token),
1624                                    dns_result_totext(DNS_R_MXISADDRESS));
1625         }
1626 }
1627
1628 static void
1629 warn_badname(dns_name_t *name, isc_lex_t *lexer,
1630              dns_rdatacallbacks_t *callbacks)
1631 {
1632         const char *file;
1633         unsigned long line;
1634         char namebuf[DNS_NAME_FORMATSIZE];
1635
1636         if (lexer != NULL) {
1637                 file = isc_lex_getsourcename(lexer);
1638                 line = isc_lex_getsourceline(lexer);
1639                 dns_name_format(name, namebuf, sizeof(namebuf));
1640                 (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
1641                                    file, line, namebuf,
1642                                    dns_result_totext(DNS_R_BADNAME));
1643         }
1644 }
1645
1646 static void
1647 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
1648                dns_rdatacallbacks_t *callbacks, const char *name,
1649                unsigned long line, isc_token_t *token, isc_result_t result)
1650 {
1651         if (name == NULL)
1652                 name = "UNKNOWN";
1653
1654         if (token != NULL) {
1655                 switch (token->type) {
1656                 case isc_tokentype_eol:
1657                         (*callback)(callbacks, "%s: %s:%lu: near eol: %s",
1658                                     "dns_rdata_fromtext", name, line,
1659                                     dns_result_totext(result));
1660                         break;
1661                 case isc_tokentype_eof:
1662                         (*callback)(callbacks, "%s: %s:%lu: near eof: %s",
1663                                     "dns_rdata_fromtext", name, line,
1664                                     dns_result_totext(result));
1665                         break;
1666                 case isc_tokentype_number:
1667                         (*callback)(callbacks, "%s: %s:%lu: near %lu: %s",
1668                                     "dns_rdata_fromtext", name, line,
1669                                     token->value.as_ulong,
1670                                     dns_result_totext(result));
1671                         break;
1672                 case isc_tokentype_string:
1673                 case isc_tokentype_qstring:
1674                         (*callback)(callbacks, "%s: %s:%lu: near '%s': %s",
1675                                     "dns_rdata_fromtext", name, line,
1676                                     DNS_AS_STR(*token),
1677                                     dns_result_totext(result));
1678                         break;
1679                 default:
1680                         (*callback)(callbacks, "%s: %s:%lu: %s",
1681                                     "dns_rdata_fromtext", name, line,
1682                                     dns_result_totext(result));
1683                         break;
1684                 }
1685         } else {
1686                 (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s",
1687                             name, line, dns_result_totext(result));
1688         }
1689 }
1690
1691 dns_rdatatype_t
1692 dns_rdata_covers(dns_rdata_t *rdata) {
1693         if (rdata->type == 46)
1694                 return (covers_rrsig(rdata));
1695         return (covers_sig(rdata));
1696 }
1697
1698 isc_boolean_t
1699 dns_rdatatype_ismeta(dns_rdatatype_t type) {
1700         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0)
1701                 return (ISC_TRUE);
1702         return (ISC_FALSE);
1703 }
1704
1705 isc_boolean_t
1706 dns_rdatatype_issingleton(dns_rdatatype_t type) {
1707         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON)
1708             != 0)
1709                 return (ISC_TRUE);
1710         return (ISC_FALSE);
1711 }
1712
1713 isc_boolean_t
1714 dns_rdatatype_notquestion(dns_rdatatype_t type) {
1715         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION)
1716             != 0)
1717                 return (ISC_TRUE);
1718         return (ISC_FALSE);
1719 }
1720
1721 isc_boolean_t
1722 dns_rdatatype_questiononly(dns_rdatatype_t type) {
1723         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY)
1724             != 0)
1725                 return (ISC_TRUE);
1726         return (ISC_FALSE);
1727 }
1728
1729 isc_boolean_t
1730 dns_rdatatype_atparent(dns_rdatatype_t type) {
1731         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0)
1732                 return (ISC_TRUE);
1733         return (ISC_FALSE);
1734 }
1735
1736 isc_boolean_t
1737 dns_rdataclass_ismeta(dns_rdataclass_t rdclass) {
1738
1739         if (rdclass == dns_rdataclass_reserved0
1740             || rdclass == dns_rdataclass_none
1741             || rdclass == dns_rdataclass_any)
1742                 return (ISC_TRUE);
1743
1744         return (ISC_FALSE);  /* Assume it is not a meta class. */
1745 }
1746
1747 isc_boolean_t
1748 dns_rdatatype_isdnssec(dns_rdatatype_t type) {
1749         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0)
1750                 return (ISC_TRUE);
1751         return (ISC_FALSE);
1752 }
1753
1754 isc_boolean_t
1755 dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
1756         if ((dns_rdatatype_attributes(type)
1757              & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH))
1758             != 0)
1759                 return (ISC_TRUE);
1760         return (ISC_FALSE);
1761 }
1762
1763 isc_boolean_t
1764 dns_rdatatype_isknown(dns_rdatatype_t type) {
1765         if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN)
1766             == 0)
1767                 return (ISC_TRUE);
1768         return (ISC_FALSE);
1769 }