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