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