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