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