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