Home | History | Annotate | Line # | Download | only in generic
      1 /*
      2  * types.h
      3  *
      4  * Copyright (c) 2023, NLnet Labs. All rights reserved.
      5  *
      6  * SPDX-License-Identifier: BSD-3-Clause
      7  *
      8  */
      9 #ifndef TYPES_H
     10 #define TYPES_H
     11 
     12 nonnull_all
     13 static really_inline int32_t scan_type_or_class(
     14   const char *data,
     15   size_t length,
     16   uint16_t *code,
     17   const mnemonic_t **mnemonic);
     18 
     19 nonnull_all
     20 static really_inline int32_t parse_type(
     21   parser_t *parser,
     22   const type_info_t *type,
     23   const rdata_info_t *field,
     24   rdata_t *rdata,
     25   const token_t *token);
     26 
     27 nonnull_all
     28 static really_inline int32_t parse_name(
     29   parser_t *parser,
     30   const type_info_t *type,
     31   const rdata_info_t *field,
     32   rdata_t *rdata,
     33   const token_t *token);
     34 
     35 nonnull_all
     36 static really_inline int32_t parse_string(
     37   parser_t *parser,
     38   const type_info_t *type,
     39   const rdata_info_t *field,
     40   rdata_t *rdata,
     41   const token_t *token);
     42 
     43 nonnull_all
     44 static really_inline int32_t parse_text(
     45   parser_t *parser,
     46   const type_info_t *type,
     47   const rdata_info_t *field,
     48   rdata_t *rdata,
     49   const token_t *token);
     50 
     51 #define FIELDS(fields) \
     52   { (sizeof(fields)/sizeof(fields[0])), fields }
     53 
     54 #define FIELD(name) \
     55   { { { name, sizeof(name) - 1 } } }
     56 
     57 #define CLASS(name, code) \
     58   { { { name, sizeof(name) - 1 }, code } }
     59 
     60 #define UNKNOWN_CLASS(code) \
     61   { { { "", 0 }, code } }
     62 
     63 #define TYPE(name, code, _class, fields, check, parse) \
     64   { { { name, sizeof(name) - 1 }, code }, _class, false, false, fields, check, parse }
     65 
     66 #define UNKNOWN_TYPE(code) \
     67   { { { "", 0 }, code }, 0, false, false, { 0, NULL }, check_generic_rr, parse_unknown_rdata }
     68 
     69 nonnull((1,2,3,4))
     70 static really_inline int32_t check_bytes(
     71   parser_t *parser,
     72   const type_info_t *type,
     73   const rdata_info_t *field,
     74   const uint8_t *data,
     75   const size_t length,
     76   const size_t size)
     77 {
     78   (void)data;
     79   if (length < size)
     80     SYNTAX_ERROR(parser, "Missing %s in %s", NAME(field), NAME(type));
     81   return (int32_t)size;
     82 }
     83 
     84 #define check_int8(...) check_bytes(__VA_ARGS__, sizeof(uint8_t))
     85 
     86 #define check_int16(...) check_bytes(__VA_ARGS__, sizeof(uint16_t))
     87 
     88 #define check_int32(...) check_bytes(__VA_ARGS__, sizeof(uint32_t))
     89 
     90 #define check_int64(...) check_bytes(__VA_ARGS__, sizeof(uint64_t))
     91 
     92 #define check_ip4(...) check_bytes(__VA_ARGS__, 4)
     93 
     94 #define check_ip6(...) check_bytes(__VA_ARGS__, 16)
     95 
     96 #define check_ilnp64(...) check_bytes(__VA_ARGS__, sizeof(uint64_t))
     97 
     98 nonnull((1,2,3,4))
     99 static really_inline int32_t check_ttl(
    100   parser_t *parser,
    101   const type_info_t *type,
    102   const rdata_info_t *field,
    103   const uint8_t *data,
    104   const size_t length)
    105 {
    106   uint32_t number;
    107 
    108   if (length < sizeof(number))
    109     SYNTAX_ERROR(parser, "Missing %s in %s", NAME(field), NAME(type));
    110 
    111   memcpy(&number, data, sizeof(number));
    112   number = be32toh(number);
    113 
    114   if (number > INT32_MAX)
    115     SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
    116 
    117   return 4;
    118 }
    119 
    120 zone_nonnull((1,2,3,4))
    121 static really_inline int32_t check_name(
    122   parser_t *parser,
    123   const type_info_t *type,
    124   const rdata_info_t *field,
    125   const uint8_t *data,
    126   const size_t length)
    127 {
    128   int32_t label = 0, count = 0;
    129   while (count < (int32_t)length) {
    130     label = data[count];
    131     count += 1 + label;
    132     if (!label)
    133       break;
    134   }
    135 
    136   if (!count || count > (int32_t)length)
    137     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
    138 
    139   return count;
    140 }
    141 
    142 zone_nonnull((1,2,3,4))
    143 static really_inline int32_t check_string(
    144   parser_t *parser,
    145   const type_info_t *type,
    146   const rdata_info_t *field,
    147   const uint8_t *data,
    148   const size_t length)
    149 {
    150   int32_t count;
    151 
    152   if (!length || (count = 1 + (int32_t)data[0]) > (int32_t)length)
    153     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
    154 
    155   return count;
    156 }
    157 
    158 zone_nonnull((1,2,3,4))
    159 static really_inline int32_t check_nsec(
    160   parser_t *parser,
    161   const type_info_t *type,
    162   const rdata_info_t *field,
    163   const uint8_t *data,
    164   const size_t length)
    165 {
    166   int32_t count = 0;
    167   int32_t last_window = -1;
    168 
    169   while ((count + 2) < (int32_t)length) {
    170     const int32_t window = (int32_t)data[0];
    171     const int32_t blocks = (int32_t)data[1];
    172     if (window <= last_window)
    173       SYNTAX_ERROR(parser, "Invalid %s in %s, windows are out-of-order",
    174                    NAME(field), NAME(type));
    175     if (!blocks || blocks > 32)
    176       SYNTAX_ERROR(parser, "Invalid %s in %s, blocks are out-of-bounds",
    177                    NAME(field), NAME(type));
    178     count += 2 + blocks;
    179     last_window = window;
    180   }
    181 
    182   if (count != (int32_t)length)
    183     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
    184 
    185   return count;
    186 }
    187 
    188 zone_nonnull((1))
    189 static really_inline int32_t check(size_t *length, int32_t count)
    190 {
    191   if (count < 0)
    192     return count;
    193   *length += (size_t)count;
    194   return 0;
    195 }
    196 
    197 nonnull_all
    198 static really_inline void adjust_line_count(file_t *file)
    199 {
    200   file->line += file->span;
    201   file->span = 0;
    202 }
    203 
    204 nonnull_all
    205 static really_inline int32_t accept_rr(
    206   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    207 {
    208   (void)type;
    209 
    210   assert(rdata->octets <= rdata->limit);
    211   assert(rdata->octets >= parser->rdata->octets);
    212   size_t length = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    213 
    214   assert(length <= UINT16_MAX);
    215   assert(parser->owner->length <= UINT8_MAX);
    216   int32_t code = parser->options.accept.callback(
    217     parser,
    218     &(zone_name_t){ (uint8_t)parser->owner->length, parser->owner->octets },
    219     parser->file->last_type,
    220     parser->file->last_class,
    221     *parser->file->ttl,
    222     (uint16_t)length,
    223     parser->rdata->octets,
    224     parser->user_data);
    225 
    226   adjust_line_count(parser->file);
    227   return code;
    228 }
    229 
    230 nonnull_all
    231 static int32_t check_a_rr(
    232   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    233 {
    234   assert(rdata->octets >= parser->rdata->octets);
    235   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets == 4)
    236     return accept_rr(parser, type, rdata);
    237   SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    238 }
    239 
    240 nonnull_all
    241 static int32_t parse_a_rdata(
    242   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    243 {
    244   int32_t code;
    245   const rdata_info_t *fields = type->rdata.fields;
    246 
    247   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    248     return code;
    249   if ((code = parse_ip4(parser, type, &fields[0], rdata, token)) < 0)
    250     return code;
    251   if ((code = take_delimiter(parser, type, token)) < 0)
    252     return code;
    253   return accept_rr(parser, type, rdata);
    254 }
    255 
    256 nonnull_all
    257 static int32_t check_ns_rr(
    258   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    259 {
    260   int32_t r;
    261   size_t c = 0;
    262   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    263   const uint8_t *o = parser->rdata->octets;
    264   const rdata_info_t *f = type->rdata.fields;
    265 
    266   if ((r = check(&c, check_name(parser, type, &f[0], o, n))) < 0)
    267     return r;
    268 
    269   if (c != n)
    270     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    271   return accept_rr(parser, type, rdata);
    272 }
    273 
    274 nonnull_all
    275 static int32_t parse_ns_rdata(
    276   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    277 {
    278   int32_t code;
    279   const rdata_info_t *fields = type->rdata.fields;
    280 
    281   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    282     return code;
    283   if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0)
    284     return code;
    285   if ((code = take_delimiter(parser, type, token)) < 0)
    286     return code;
    287   return accept_rr(parser, type, rdata);
    288 }
    289 
    290 nonnull_all
    291 static int32_t check_soa_rr(
    292   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    293 {
    294   int32_t r;
    295   size_t c = 0;
    296   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    297   const uint8_t *o = parser->rdata->octets;
    298   const rdata_info_t *f = type->rdata.fields;
    299 
    300   if ((r = check(&c, check_name(parser, type, &f[0], o, n))) ||
    301       (r = check(&c, check_name(parser, type, &f[1], o+c, n-c))) ||
    302       (r = check(&c, check_int32(parser, type, &f[2], o+c, n-c))) ||
    303       (r = check(&c, check_ttl(parser, type, &f[3], o+c, n-c))) ||
    304       (r = check(&c, check_ttl(parser, type, &f[4], o+c, n-c))) ||
    305       (r = check(&c, check_ttl(parser, type, &f[5], o+c, n-c))) ||
    306       (r = check(&c, check_ttl(parser, type, &f[6], o+c, n-c))))
    307     return r;
    308 
    309   if (c != n)
    310     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    311   return accept_rr(parser, type, rdata);
    312 }
    313 
    314 nonnull_all
    315 static int32_t parse_soa_rdata(
    316   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    317 {
    318   int32_t code;
    319   const rdata_info_t *fields = type->rdata.fields;
    320 
    321   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    322     return code;
    323   if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0)
    324     return code;
    325   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    326     return code;
    327   if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0)
    328     return code;
    329   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
    330     return code;
    331   if ((code = parse_int32(parser, type, &fields[2], rdata, token)) < 0)
    332     return code;
    333   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
    334     return code;
    335   if ((code = parse_ttl(parser, type, &fields[3], rdata, token)) < 0)
    336     return code;
    337   if ((code = take_contiguous(parser, type, &fields[4], token)) < 0)
    338     return code;
    339   if ((code = parse_ttl(parser, type, &fields[4], rdata, token)) < 0)
    340     return code;
    341   if ((code = take_contiguous(parser, type, &fields[5], token)) < 0)
    342     return code;
    343   if ((code = parse_ttl(parser, type, &fields[5], rdata, token)) < 0)
    344     return code;
    345   if ((code = take_contiguous(parser, type, &fields[6], token)) < 0)
    346     return code;
    347   if ((code = parse_ttl(parser, type, &fields[6], rdata, token)) < 0)
    348     return code;
    349   if ((code = take_delimiter(parser, type, token)) < 0)
    350     return code;
    351   return accept_rr(parser, type, rdata);
    352 }
    353 
    354 nonnull_all
    355 static int32_t check_wks_rr(
    356   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    357 {
    358   int32_t r;
    359   size_t c = 0;
    360   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    361   const uint8_t *o = parser->rdata->octets;
    362   const rdata_info_t *f = type->rdata.fields;
    363 
    364   if ((r = check(&c, check_ip4(parser, type, &f[0], o, n))) ||
    365       (r = check(&c, check_int8(parser, type, &f[0], o+c, n-c))))
    366     return r;
    367 
    368   // any bit may, or may not, be set. confirm the bitmap does not exceed the
    369   // maximum number of ports
    370   if (n > 8192 + 5)
    371     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    372 
    373   return accept_rr(parser, type, rdata);
    374 }
    375 
    376 nonnull_all
    377 static int32_t parse_wks_rdata(
    378   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    379 {
    380   int32_t code;
    381   const rdata_info_t *fields = type->rdata.fields;
    382 
    383   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    384     return code;
    385   if ((code = parse_ip4(parser, type, &fields[0], rdata, token) < 0))
    386     return code;
    387 
    388   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    389     return code;
    390 
    391   uint8_t protocol;
    392   if (!scan_protocol(token->data, token->length, &protocol))
    393     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type));
    394 
    395   *rdata->octets++ = protocol;
    396   uint8_t *bitmap = rdata->octets;
    397   int32_t highest_port = -1;
    398 
    399   take(parser, token);
    400   while (is_contiguous(token)) {
    401     uint16_t port;
    402     if (!scan_service(token->data, token->length, protocol, &port))
    403       SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&type->rdata.fields[2]), NAME(type));
    404 
    405     if (port > highest_port) {
    406       // ensure newly used octets are zeroed out before use
    407       size_t offset = highest_port < 0 ? 0 : (size_t)highest_port / 8 + 1;
    408       size_t length = (size_t)port / 8 + 1;
    409       memset(bitmap + offset, 0, length - offset);
    410       highest_port = port;
    411     }
    412 
    413     // bits are counted from left to right, so bit 0 is the left most bit
    414     bitmap[port / 8] |= (1 << (7 - port % 8));
    415     take(parser, token);
    416   }
    417 
    418   rdata->octets += (size_t)highest_port / 8 + 1;
    419 
    420   if (have_delimiter(parser, type, token) < 0)
    421     return token->code;
    422   return accept_rr(parser, type, rdata);
    423 }
    424 
    425 nonnull_all
    426 static int32_t check_hinfo_rr(
    427   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    428 {
    429   int32_t r;
    430   size_t c = 0;
    431   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    432   const uint8_t *o = parser->rdata->octets;
    433   const rdata_info_t *f = type->rdata.fields;
    434 
    435   if ((r = check(&c, check_string(parser, type, &f[0], o, n))) ||
    436       (r = check(&c, check_string(parser, type, &f[1], o+c, n-c))))
    437     return r;
    438 
    439   if (c != n)
    440     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    441   return accept_rr(parser, type, rdata);
    442 }
    443 
    444 nonnull_all
    445 static int32_t parse_hinfo_rdata(
    446   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    447 {
    448   int32_t code;
    449   const rdata_info_t *fields = type->rdata.fields;
    450 
    451   if ((code = have_contiguous_or_quoted(parser, type, &fields[0], token)) < 0)
    452     return code;
    453   if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0)
    454     return code;
    455   if ((code = take_quoted_or_contiguous(parser, type, &fields[1], token)) < 0)
    456     return code;
    457   if ((code = parse_string(parser, type, &fields[1], rdata, token)) < 0)
    458     return code;
    459   if ((code = take_delimiter(parser, type, token)) < 0)
    460     return code;
    461   return accept_rr(parser, type, rdata);
    462 }
    463 
    464 nonnull_all
    465 static int32_t check_minfo_rr(
    466   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    467 {
    468   int32_t r;
    469   size_t c = 0;
    470   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    471   const uint8_t *o = parser->rdata->octets;
    472   const rdata_info_t *f = type->rdata.fields;
    473 
    474   if ((r = check(&c, check_name(parser, type, &f[0], o, n))) ||
    475       (r = check(&c, check_name(parser, type, &f[1], o+c, n-c))))
    476     return r;
    477 
    478   if (c != n)
    479     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    480   return accept_rr(parser, type, rdata);
    481 }
    482 
    483 nonnull_all
    484 static int32_t parse_minfo_rdata(
    485   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    486 {
    487   int32_t code;
    488   const rdata_info_t *fields = type->rdata.fields;
    489 
    490   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    491     return code;
    492   if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0)
    493     return code;
    494   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    495     return code;
    496   if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0)
    497     return code;
    498   if ((code = take_delimiter(parser, type, token)) < 0)
    499     return code;
    500   return accept_rr(parser, type, rdata);
    501 }
    502 
    503 nonnull_all
    504 static int32_t check_mx_rr(
    505   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    506 {
    507   int32_t r;
    508   size_t c = 0;
    509   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    510   const uint8_t *o = parser->rdata->octets;
    511   const rdata_info_t *f = type->rdata.fields;
    512 
    513   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
    514       (r = check(&c, check_name(parser, type, &f[1], o+c, n-c))))
    515     return r;
    516 
    517   if (c != n)
    518     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    519   return accept_rr(parser, type, rdata);
    520 }
    521 
    522 nonnull_all
    523 static int32_t parse_mx_rdata(
    524   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    525 {
    526   int32_t code;
    527   const rdata_info_t *fields = type->rdata.fields;
    528 
    529   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    530     return code;
    531   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
    532     return code;
    533   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    534     return code;
    535   if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0)
    536     return code;
    537   if ((code = take_delimiter(parser, type, token)) < 0)
    538     return code;
    539   return accept_rr(parser, type, rdata);
    540 }
    541 
    542 nonnull_all
    543 static int32_t check_txt_rr(
    544   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    545 {
    546   int32_t r;
    547   size_t c = 0;
    548   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    549   const uint8_t *o = parser->rdata->octets;
    550   const rdata_info_t *f = type->rdata.fields;
    551 
    552   if ((r = check(&c, check_string(parser, type, &f[0], o, n))))
    553     return r;
    554 
    555   while (c < n)
    556     if ((r = check(&c, check_string(parser, type, &f[0], o+c, n-c))))
    557       return r;
    558 
    559   if (c != n)
    560     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    561   return accept_rr(parser, type, rdata);
    562 }
    563 
    564 nonnull_all
    565 static int32_t parse_txt_rdata(
    566   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    567 {
    568   int32_t code;
    569   const rdata_info_t *fields = type->rdata.fields;
    570 
    571   while (is_contiguous_or_quoted(token)) {
    572     if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0)
    573       return code;
    574     take(parser, token);
    575   }
    576 
    577   if ((code = have_delimiter(parser, type, token)) < 0)
    578     return code;
    579   return accept_rr(parser, type, rdata);
    580 }
    581 
    582 nonnull_all
    583 static int32_t check_x25_rr(
    584   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    585 {
    586   int32_t r;
    587   size_t c = 0;
    588   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    589   const uint8_t *o = parser->rdata->octets;
    590   const rdata_info_t *f = type->rdata.fields;
    591 
    592   if ((r = check(&c, check_string(parser, type, &f[0], o, n))))
    593     return r;
    594 
    595   if (c != n)
    596     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    597   return accept_rr(parser, type, rdata);
    598 }
    599 
    600 nonnull_all
    601 static int32_t parse_x25_rdata(
    602   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    603 {
    604   int32_t code;
    605   const rdata_info_t *fields = type->rdata.fields;
    606 
    607   if ((code = have_contiguous_or_quoted(parser, type, &fields[0], token)) < 0)
    608     return code;
    609   if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0)
    610     return code;
    611   if ((code = take_delimiter(parser, type, token)) < 0)
    612     return code;
    613   return accept_rr(parser, type, rdata);
    614 }
    615 
    616 nonnull_all
    617 static int32_t check_isdn_rr(
    618   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    619 {
    620   int32_t r;
    621   size_t c = 0;
    622   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    623   const uint8_t *o = parser->rdata->octets;
    624   const rdata_info_t *f = type->rdata.fields;
    625 
    626   if ((r = check(&c, check_string(parser, type, &f[0], o, n))))
    627     return r;
    628   // subaddress is optional
    629   if (c < n && (r = check(&c, check_string(parser, type, &f[1], o+c, n-c))))
    630     return r;
    631 
    632   if (c != n)
    633     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    634   return accept_rr(parser, type, rdata);
    635 }
    636 
    637 nonnull_all
    638 static int32_t parse_isdn_rdata(
    639   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    640 {
    641   int32_t code;
    642   const rdata_info_t *fields = type->rdata.fields;
    643 
    644   if ((code = have_contiguous_or_quoted(parser, type, &fields[0], token)) < 0)
    645     return code;
    646   if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0)
    647     return code;
    648 
    649   // subaddress is optional
    650   take(parser, token);
    651   if (is_contiguous_or_quoted(token)) {
    652     if ((code = parse_string(parser, type, &fields[1], rdata, token)) < 0)
    653       return code;
    654     take(parser, token);
    655   }
    656 
    657   if ((code = have_delimiter(parser, type, token)) < 0)
    658     return code;
    659   return accept_rr(parser, type, rdata);
    660 }
    661 
    662 nonnull_all
    663 static int32_t check_rt_rr(
    664   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    665 {
    666   int32_t r;
    667   size_t c = 0;
    668   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    669   const uint8_t *o = parser->rdata->octets;
    670   const rdata_info_t *f = type->rdata.fields;
    671 
    672   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
    673       (r = check(&c, check_name(parser, type, &f[1], o+c, n-c))))
    674     return r;
    675 
    676   if (c != n)
    677     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    678   return accept_rr(parser, type, rdata);
    679 }
    680 
    681 nonnull_all
    682 static int32_t parse_rt_rdata(
    683   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    684 {
    685   int32_t code;
    686   const rdata_info_t *fields = type->rdata.fields;
    687 
    688   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    689     return code;
    690   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
    691     return code;
    692   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    693     return code;
    694   if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0)
    695     return code;
    696   if ((code = take_delimiter(parser, type, token)) < 0)
    697     return code;
    698   return accept_rr(parser, type, rdata);
    699 }
    700 
    701 nonnull_all
    702 static int32_t check_nsap_rr(
    703   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    704 {
    705   if (rdata->octets == parser->rdata->octets)
    706     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    707   return accept_rr(parser, type, rdata);
    708 }
    709 
    710 nonnull_all
    711 static int32_t parse_nsap_rdata(
    712   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    713 {
    714   int32_t code;
    715   const rdata_info_t *fields = type->rdata.fields;
    716 
    717   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    718     return code;
    719   if ((code = parse_nsap(parser, type, &fields[0], rdata, token)) < 0)
    720     return code;
    721   if ((code = take_delimiter(parser, type, token)) < 0)
    722     return code;
    723   return accept_rr(parser, type, rdata);
    724 }
    725 
    726 nonnull_all
    727 static int32_t check_nsap_ptr_rr(
    728   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    729 {
    730   {
    731     int32_t r;
    732     size_t c = 0;
    733     const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    734     const uint8_t *o = parser->rdata->octets;
    735     const rdata_info_t *f = type->rdata.fields;
    736 
    737     if ((r = check(&c, check_string(parser, type, &f[0], o, n))))
    738       return r;
    739 
    740     if (c != n)
    741       SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    742   }
    743 
    744   {
    745     // RFC1706 section 6
    746     // A domain name is generated from an NSAP by reversing the hex nibbles of
    747     // the NSAP, treating each nibble as a separate subdomain, and appending
    748     // the top-level subdomain name "NSAP.INT" to it. For example, the domain
    749     // name used in the reverse lookup for the NSAP
    750     //
    751     //    47.0005.80.005a00.0000.0001.e133.ffffff000162.00
    752     //
    753     // would appear as
    754     //
    755     //    0.0.2.6.1.0.0.0.f.f.f.f.f.f.3.3.1.e.1.0.0.0.0.0.0.0.0.0.a.5.0.0.
    756     //                        0.8.5.0.0.0.7.4.NSAP.INT.
    757     size_t i = 0;
    758     const size_t n = parser->file->owner.length;
    759     const uint8_t *o = parser->file->owner.octets;
    760     for (; i < n; i += 2)
    761       if (o[i] != 1 || (base16_table_dec_32bit_d1[o[i+1]] > 0xff))
    762         break;
    763 
    764     const uint8_t nsap_int[] = { 4, 'n', 's', 'a', 'p', 3, 'i', 'n', 't', 0 };
    765     if (strncasecmp((const char *)o + i, (const char *)nsap_int, 9) != 0 || !i || i + 10 != n)
    766       SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
    767   }
    768 
    769   return accept_rr(parser, type, rdata);
    770 }
    771 
    772 nonnull_all
    773 static int32_t parse_nsap_ptr_rdata(
    774   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    775 {
    776   int32_t code;
    777   const rdata_info_t *fields = type->rdata.fields;
    778 
    779   if ((code = have_contiguous_or_quoted(parser, type, &fields[0], token)) < 0)
    780     return code;
    781   if ((code = parse_string(parser, type, &fields[0], rdata, token)) < 0)
    782     return code;
    783   if ((code = take_delimiter(parser, type, token)) < 0)
    784     return code;
    785 
    786   // RFC1706 section 6 states each nibble is treated as a separate subdomain
    787   return check_nsap_ptr_rr(parser, type, rdata);
    788 }
    789 
    790 nonnull_all
    791 static int32_t check_key_rr(
    792   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    793 {
    794 #if 0
    795   int32_t r;
    796   size_t c = 0;
    797   const size_t n = parser->rdata->length;
    798   const uint8_t *o = parser->rdata->octets;
    799   const rdata_info_t *f = type->rdata.fields;
    800 
    801   //
    802   // FIXME: implement (RFC2065)
    803   //
    804   // FIXME: verify the flag, algorithm and protocol combination is valid
    805   // FIXME: verify the key is valid for type(3)+algorithm(1)
    806   //
    807   // The combination is of course subject to secondary checks!
    808   //
    809 #endif
    810   (void)type;
    811   return accept_rr(parser, type, rdata);
    812 }
    813 
    814 nonnull_all
    815 static int32_t parse_key_rdata(
    816   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    817 {
    818   int32_t code;
    819   const rdata_info_t *fields = type->rdata.fields;
    820 
    821   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    822     return code;
    823   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
    824     return code;
    825   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    826     return code;
    827   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
    828     return code;
    829   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
    830     return code;
    831   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
    832     return code;
    833   take(parser, token);
    834   if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0)
    835     return code;
    836 
    837   return check_key_rr(parser, type, rdata);
    838 }
    839 
    840 nonnull_all
    841 static int32_t check_px_rr(
    842   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    843 {
    844   int32_t r;
    845   size_t c = 0;
    846   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    847   const uint8_t *o = parser->rdata->octets;
    848   const rdata_info_t *f = type->rdata.fields;
    849 
    850   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
    851       (r = check(&c, check_name(parser, type, &f[1], o+c, n-c))) ||
    852       (r = check(&c, check_name(parser, type, &f[2], o+c, n-c))))
    853     return r;
    854 
    855   if (c != n)
    856     SYNTAX_ERROR(parser, "Invalid %s record", NAME(type));
    857   return accept_rr(parser, type, rdata);
    858 }
    859 
    860 nonnull_all
    861 static int32_t parse_px_rdata(
    862   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    863 {
    864   int32_t code;
    865   const rdata_info_t *fields = type->rdata.fields;
    866 
    867   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    868     return code;
    869   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
    870     return code;
    871   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    872     return code;
    873   if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0)
    874     return code;
    875   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
    876     return code;
    877   if ((code = parse_name(parser, type, &fields[2], rdata, token)) < 0)
    878     return code;
    879   if ((code = take_delimiter(parser, type, token)) < 0)
    880     return code;
    881   return accept_rr(parser, type, rdata);
    882 }
    883 
    884 nonnull_all
    885 static int32_t check_gpos_rr(
    886   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    887 {
    888   int32_t r;
    889   size_t c = 0;
    890   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    891   const uint8_t *o = parser->rdata->octets;
    892   const rdata_info_t *f = type->rdata.fields;
    893 
    894   if ((r = check(&c, check_string(parser, type, &f[0], o, n))) ||
    895       (r = check(&c, check_string(parser, type, &f[1], o+c, n-c))) ||
    896       (r = check(&c, check_string(parser, type, &f[2], o+c, n-c))))
    897     return r;
    898 
    899   if (c != n)
    900     SYNTAX_ERROR(parser, "Invalid %s record", NAME(type));
    901   return accept_rr(parser, type, rdata);
    902 }
    903 
    904 static int32_t parse_gpos_rdata(
    905   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    906 {
    907   int32_t code;
    908   const rdata_info_t *fields = type->rdata.fields;
    909 
    910   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    911     return code;
    912   if ((code = parse_latitude(parser, type, &fields[0], rdata, token)) < 0)
    913     return code;
    914   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
    915     return code;
    916   if ((code = parse_longitude(parser, type, &fields[1], rdata, token)) < 0)
    917     return code;
    918   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
    919     return code;
    920   if ((code = parse_altitude(parser, type, &fields[2], rdata, token)) < 0)
    921     return code;
    922   if ((code = take_delimiter(parser, type, token)) < 0)
    923     return code;
    924   return accept_rr(parser, type, rdata);
    925 }
    926 
    927 nonnull_all
    928 static int32_t check_aaaa_rr(
    929   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    930 {
    931   int32_t r;
    932   size_t c = 0;
    933   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
    934   const uint8_t *o = parser->rdata->octets;
    935   const rdata_info_t *f = type->rdata.fields;
    936 
    937   if ((r = check(&c, check_ip6(parser, type, &f[0], o, n))))
    938     return r;
    939 
    940   if (c != n)
    941     SYNTAX_ERROR(parser, "Invalid %s record", NAME(type));
    942   return accept_rr(parser, type, rdata);
    943 }
    944 
    945 nonnull_all
    946 static int32_t parse_aaaa_rdata(
    947   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    948 {
    949   int32_t code;
    950   const rdata_info_t *fields = type->rdata.fields;
    951 
    952   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
    953     return code;
    954   if ((code = parse_ip6(parser, type, &fields[0], rdata, token)) < 0)
    955     return code;
    956   if ((code = take_delimiter(parser, type, token)) < 0)
    957     return code;
    958   return accept_rr(parser, type, rdata);
    959 }
    960 
    961 nonnull_all
    962 static int32_t check_loc_rr(
    963   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
    964 {
    965   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets != 16)
    966     SYNTAX_ERROR(parser, "Invalid %s record", NAME(type));
    967   return accept_rr(parser, type, rdata);
    968 
    969   // FIXME: check validity of latitude, longitude and latitude?
    970 }
    971 
    972 nonnull_all
    973 static int32_t parse_loc_rdata(
    974   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
    975 {
    976   int32_t code;
    977   uint32_t degrees, minutes, seconds;
    978   uint32_t latitude, longitude, altitude;
    979   const rdata_info_t *fields = type->rdata.fields;
    980   static const uint8_t defaults[4] = { 0x00, 0x12, 0x16, 0x13 };
    981 
    982   // RFC1876 section 3:
    983   // If omitted, minutes and seconds default to zero, size defaults to 1m,
    984   // horizontal precision defaults to 10000m, and vertical precision defaults
    985   // to 10m.
    986   memcpy(rdata->octets, &defaults, sizeof(defaults));
    987 
    988   // latitude
    989   if ((code = have_contiguous(parser, type, &fields[4], token)) < 0)
    990     return code;
    991   if (scan_degrees(token->data, token->length, &degrees) == -1)
    992     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[4]), NAME(type));
    993   if ((code = take_contiguous(parser, type, &fields[4], token)) < 0)
    994     return code;
    995   if (scan_minutes(token->data, token->length, &minutes) == -1)
    996     goto north_south; // minutes default to zero
    997   degrees += minutes;
    998   if ((code = take_contiguous(parser, type, &fields[4], token)) < 0)
    999     return code;
   1000   if (scan_seconds(token->data, token->length, &seconds) == -1)
   1001     goto north_south; // seconds default to zero
   1002   degrees += seconds;
   1003 
   1004   if ((code = take_contiguous(parser, type, &fields[4], token)) < 0)
   1005     return code;
   1006 north_south:
   1007   if (token->data[0] == 'N')
   1008     latitude = htobe32((1u<<31) + degrees);
   1009   else if (token->data[0] == 'S')
   1010     latitude = htobe32((1u<<31) - degrees);
   1011   else
   1012     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[4]), NAME(type));
   1013 
   1014   memcpy(&rdata->octets[4], &latitude, sizeof(latitude));
   1015 
   1016   // longitude
   1017   if ((code = take_contiguous(parser, type, &fields[5], token)) < 0)
   1018     return code;
   1019   if (scan_degrees(token->data, token->length, &degrees) == -1)
   1020     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[5]), NAME(type));
   1021   if ((code = take_contiguous(parser, type, &fields[5], token)) < 0)
   1022     return code;
   1023   if (scan_minutes(token->data, token->length, &minutes) == -1)
   1024     goto east_west; // minutes default to zero
   1025   degrees += minutes;
   1026   if ((code = take_contiguous(parser, type, &fields[5], token)) < 0)
   1027     return code;
   1028   if (scan_seconds(token->data, token->length, &seconds) == -1)
   1029     goto east_west; // seconds default to zero
   1030   degrees += seconds;
   1031 
   1032   if ((code = take_contiguous(parser, type, &fields[5], token)) < 0)
   1033     return code;
   1034 east_west:
   1035   if (token->data[0] == 'E')
   1036     longitude = htobe32((1u<<31) + degrees);
   1037   else if (token->data[0] == 'W')
   1038     longitude = htobe32((1u<<31) - degrees);
   1039   else
   1040     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[5]), NAME(type));
   1041 
   1042   memcpy(&rdata->octets[8], &longitude, sizeof(longitude));
   1043 
   1044   // altitude
   1045   if ((code = take_contiguous(parser, type, &fields[6], token)) < 0)
   1046     return code;
   1047   if (scan_altitude(token->data, token->length, &altitude) == -1)
   1048     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[6]), NAME(type));
   1049 
   1050   altitude = htobe32(altitude);
   1051   memcpy(&rdata->octets[12], &altitude, sizeof(altitude));
   1052 
   1053   // size
   1054   take(parser, token);
   1055   if (!is_contiguous(token))
   1056     goto skip_optional;
   1057   if (scan_precision(token->data, token->length, &rdata->octets[1]))
   1058     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type));
   1059 
   1060   // horizontal precision
   1061   take(parser, token);
   1062   if (!is_contiguous(token))
   1063     goto skip_optional;
   1064   if (scan_precision(token->data, token->length, &rdata->octets[2]))
   1065     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[2]), NAME(type));
   1066 
   1067   // vertical precision
   1068   take(parser, token);
   1069   if (!is_contiguous(token))
   1070     goto skip_optional;
   1071   if (scan_precision(token->data, token->length, &rdata->octets[3]))
   1072     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type));
   1073 
   1074   take(parser, token);
   1075 skip_optional:
   1076   if ((code = have_delimiter(parser, type, token)) < 0)
   1077     return code;
   1078 
   1079   rdata->octets += 16;
   1080   return accept_rr(parser, type, rdata);
   1081 }
   1082 
   1083 nonnull_all
   1084 static int32_t check_nxt_rr(
   1085   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1086 {
   1087   int32_t r;
   1088   size_t c = 0;
   1089   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1090   const uint8_t *o = parser->rdata->octets;
   1091   const rdata_info_t *f = type->rdata.fields;
   1092 
   1093   if ((r = check(&c, check_name(parser, type, &f[0], o+c, n-c))))
   1094     return r;
   1095 
   1096   return accept_rr(parser, type, rdata);
   1097 }
   1098 
   1099 nonnull_all
   1100 static int32_t parse_nxt_rdata(
   1101   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1102 {
   1103   int32_t code;
   1104   const rdata_info_t *fields = type->rdata.fields;
   1105 
   1106   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1107     return code;
   1108   if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0)
   1109     return code;
   1110   take(parser, token);
   1111   if ((code = parse_nxt(parser, type, &fields[1], rdata, token)) < 0)
   1112     return code;
   1113 
   1114   return accept_rr(parser, type, rdata);
   1115 }
   1116 
   1117 nonnull_all
   1118 static int32_t check_eid_rr(
   1119   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1120 {
   1121   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets <= 0)
   1122     SYNTAX_ERROR(parser, "Invalid %s record", NAME(type));
   1123   return accept_rr(parser, type, rdata);
   1124 }
   1125 
   1126 nonnull_all
   1127 static int32_t parse_eid_rdata(
   1128   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1129 {
   1130   int32_t code;
   1131   const rdata_info_t *fields = type->rdata.fields;
   1132 
   1133   if ((code = parse_base16_sequence(parser, type, &fields[1], rdata, token)) < 0)
   1134     return code;
   1135   return check_eid_rr(parser, type, rdata);
   1136 }
   1137 
   1138 nonnull_all
   1139 static int32_t check_srv_rr(
   1140   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1141 {
   1142   int32_t r;
   1143   size_t c = 0;
   1144   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1145   const uint8_t *o = parser->rdata->octets;
   1146   const rdata_info_t *f = type->rdata.fields;
   1147 
   1148   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   1149       (r = check(&c, check_int16(parser, type, &f[1], o+c, n-c))) ||
   1150       (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) ||
   1151       (r = check(&c, check_name(parser, type, &f[3], o+c, n-c))))
   1152     return r;
   1153 
   1154   if (c != n)
   1155     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1156   return accept_rr(parser, type, rdata);
   1157 }
   1158 
   1159 nonnull_all
   1160 static int32_t parse_srv_rdata(
   1161   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1162 {
   1163   int32_t code;
   1164   const rdata_info_t *fields = type->rdata.fields;
   1165 
   1166   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1167     return code;
   1168   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   1169     return code;
   1170   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1171     return code;
   1172   if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0)
   1173     return code;
   1174   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1175     return code;
   1176   if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0)
   1177     return code;
   1178   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   1179     return code;
   1180   if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0)
   1181     return code;
   1182   if ((code = take_delimiter(parser, type, token)) < 0)
   1183     return code;
   1184   return accept_rr(parser, type, rdata);
   1185 }
   1186 
   1187 nonnull_all
   1188 static int32_t check_atma_rr(
   1189   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1190 {
   1191   assert(rdata->octets >= parser->rdata->octets);
   1192   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets > 2)
   1193     return accept_rr(parser, type, rdata);
   1194   SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1195 }
   1196 
   1197 nonnull_all
   1198 static int32_t parse_atma_rdata(
   1199   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1200 {
   1201   int32_t code;
   1202   const rdata_info_t *fields = type->rdata.fields;
   1203 
   1204   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1205     return code;
   1206   if ((code = parse_atma(parser, type, &fields[0], rdata, token)) < 0)
   1207     return code;
   1208   if ((code = take_delimiter(parser, type, token)) < 0)
   1209     return code;
   1210   return accept_rr(parser, type, rdata);
   1211 }
   1212 
   1213 nonnull_all
   1214 static int32_t check_naptr_rr(
   1215   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1216 {
   1217   // FIXME: implement actual checks
   1218   (void)type;
   1219   return accept_rr(parser, type, rdata);
   1220 }
   1221 
   1222 nonnull_all
   1223 static int32_t parse_naptr_rdata(
   1224   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1225 {
   1226   int32_t code;
   1227   const rdata_info_t *fields = type->rdata.fields;
   1228 
   1229   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1230     return code;
   1231   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   1232     return code;
   1233   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1234     return code;
   1235   if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0)
   1236     return code;
   1237   if ((code = take_quoted_or_contiguous(parser, type, &fields[2], token)) < 0)
   1238     return code;
   1239   if ((code = parse_string(parser, type, &fields[2], rdata, token)) < 0)
   1240     return code;
   1241   if ((code = take_quoted_or_contiguous(parser, type, &fields[3], token)) < 0)
   1242     return code;
   1243   if ((code = parse_string(parser, type, &fields[3], rdata, token)) < 0)
   1244     return code;
   1245   if ((code = take_quoted_or_contiguous(parser, type, &fields[4], token)) < 0)
   1246     return code;
   1247   if ((code = parse_string(parser, type, &fields[4], rdata, token)) < 0)
   1248     return code;
   1249   if ((code = take_contiguous(parser, type, &fields[5], token)) < 0)
   1250     return code;
   1251   if ((code = parse_name(parser, type, &fields[5], rdata, token)) < 0)
   1252     return code;
   1253   if ((code = take_delimiter(parser, type, token)) < 0)
   1254     return code;
   1255   return accept_rr(parser, type, rdata);
   1256 }
   1257 
   1258 nonnull_all
   1259 static int32_t check_cert_rr(
   1260   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1261 {
   1262   // FIXME: implement actual checks
   1263   (void)type;
   1264 
   1265   assert(rdata->octets >= parser->rdata->octets);
   1266   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 6)
   1267     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1268   return accept_rr(parser, type, rdata);
   1269 }
   1270 
   1271 nonnull_all
   1272 static int32_t parse_cert_rdata(
   1273   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1274 {
   1275   int32_t code;
   1276   const rdata_info_t *fields = type->rdata.fields;
   1277 
   1278   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1279     return code;
   1280   if ((code = parse_certificate_type(parser, type, &fields[0], rdata, token)) < 0)
   1281     return code;
   1282   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1283     return code;
   1284   if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0)
   1285     return code;
   1286   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1287     return code;
   1288   if ((code = parse_algorithm(parser, type, &fields[2], rdata, token)) < 0)
   1289     return code;
   1290   take(parser, token);
   1291   if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0)
   1292     return code;
   1293 
   1294   return accept_rr(parser, type, rdata);
   1295 }
   1296 
   1297 nonnull_all
   1298 static int32_t check_sink_rr(
   1299   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1300 {
   1301   // FIXME: implement actual checks
   1302   (void)type;
   1303 
   1304   assert(rdata->octets >= parser->rdata->octets);
   1305   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 3)
   1306     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1307   return accept_rr(parser, type, rdata);
   1308 }
   1309 
   1310 nonnull_all
   1311 static int32_t parse_sink_rdata(
   1312   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1313 {
   1314   int32_t code;
   1315   const rdata_info_t *fields = type->rdata.fields;
   1316 
   1317   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1318     return code;
   1319   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   1320     return code;
   1321   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1322     return code;
   1323   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   1324     return code;
   1325   take(parser, token);
   1326   if ((code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0)
   1327     return code;
   1328 
   1329   return accept_rr(parser, type, rdata);
   1330 }
   1331 
   1332 nonnull_all
   1333 static int32_t check_apl_rr(
   1334   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1335 {
   1336   // FIXME: check correctness of fields and total length
   1337   return accept_rr(parser, type, rdata);
   1338 }
   1339 
   1340 nonnull_all
   1341 static int32_t parse_apl_rdata(
   1342   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1343 {
   1344   int32_t code;
   1345   const rdata_info_t *fields = type->rdata.fields;
   1346 
   1347   // RDATA section for APL consists of zero or more fields
   1348   while (is_contiguous(token)) {
   1349     int32_t length;
   1350     const size_t size = (uintptr_t)rdata->limit - (uintptr_t)rdata->octets;
   1351     if ((length = scan_apl(token->data, token->length, rdata->octets, size)) < 0)
   1352       SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[0]), NAME(type));
   1353     assert(length == 8 /* ipv4 */ || length == 20 /* ipv6 */);
   1354     rdata->octets += (size_t)length;
   1355     take(parser, token);
   1356   }
   1357 
   1358   if ((code = have_delimiter(parser, type, token)) < 0)
   1359     return code;
   1360   return accept_rr(parser, type, rdata);
   1361 }
   1362 
   1363 nonnull_all
   1364 static int32_t check_ds_rr(
   1365   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1366 {
   1367   int32_t r;
   1368   size_t c = 0;
   1369   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1370   const uint8_t *o = parser->rdata->octets;
   1371   const rdata_info_t *f = type->rdata.fields;
   1372 
   1373   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   1374       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   1375       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))))
   1376     return r;
   1377 
   1378   const uint8_t digest_algorithm = parser->rdata->octets[3];
   1379 
   1380   if ((digest_algorithm & 0x7) == digest_algorithm) {
   1381     // https://www.iana.org/assignments/ds-rr-types
   1382     static const uint8_t digest_sizes[8] = {
   1383       0,  // 0: Reserved
   1384       20, // 1: SHA-1
   1385       32, // 2: SHA-256
   1386       32, // 3: GOST R 34.11-94
   1387       48, // 4: SHA-384
   1388       32, // 5: GOST R 34.10-2012
   1389       32, // 6: SM3
   1390       0   // 7: Unassigned
   1391     };
   1392 
   1393     const uint8_t digest_size = digest_sizes[ digest_algorithm ];
   1394 
   1395     if (digest_size && n - 4 != digest_size)
   1396       SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type));
   1397   }
   1398 
   1399   if (c > n)
   1400     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1401   return accept_rr(parser, type, rdata);
   1402 }
   1403 
   1404 nonnull_all
   1405 static int32_t parse_ds_rdata(
   1406   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1407 {
   1408   int32_t code;
   1409   const rdata_info_t *fields = type->rdata.fields;
   1410 
   1411   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1412     return code;
   1413   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   1414     return code;
   1415   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1416     return code;
   1417   if ((code = parse_algorithm(parser, type, &fields[1], rdata, token)) < 0)
   1418     return code;
   1419   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1420     return code;
   1421   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
   1422     return code;
   1423   take(parser, token);
   1424   if (!(token->length == 1 && (char)*token->data == '0')
   1425   &&  (code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0)
   1426     return code;
   1427 
   1428   const uint8_t digest_algorithm = parser->rdata->octets[3];
   1429 
   1430   if ((digest_algorithm & 0x7) == digest_algorithm) {
   1431     // https://www.iana.org/assignments/ds-rr-types
   1432     static const uint8_t digest_sizes[8] = {
   1433       0,  // 0: Reserved
   1434       20, // 1: SHA-1
   1435       32, // 2: SHA-256
   1436       32, // 3: GOST R 34.11-94
   1437       48, // 4: SHA-384
   1438       32, // 5: GOST R 34.10-2012
   1439       32, // 6: SM3
   1440       0   // 7: Unassigned
   1441     };
   1442 
   1443     const uint8_t digest_size = digest_sizes[ digest_algorithm ];
   1444     size_t length = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1445 
   1446     if (digest_size && length - 4 != digest_size)
   1447       SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type));
   1448   }
   1449 
   1450   return accept_rr(parser, type, rdata);
   1451 }
   1452 
   1453 nonnull_all
   1454 static int32_t check_sshfp_rr(
   1455   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1456 {
   1457   int32_t r;
   1458   size_t c = 0;
   1459   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1460   const uint8_t *o = parser->rdata->octets;
   1461   const rdata_info_t *f = type->rdata.fields;
   1462 
   1463   if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) ||
   1464       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))))
   1465     return r;
   1466 
   1467   // https://www.iana.org/assignments/dns-sshfp-rr-parameters
   1468 
   1469   if (c == n)
   1470     SYNTAX_ERROR(parser, "Missing %s in %s", NAME((&f[n!=0])), NAME(type));
   1471   else if (o[1] == 1 && (n - c) != 20)
   1472     SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s",
   1473                            "SHA1", NAME(type));
   1474   else if (o[1] == 2 && (n - c) != 32)
   1475     SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s",
   1476                            "SHA256", NAME(type));
   1477 
   1478   return accept_rr(parser, type, rdata);
   1479 }
   1480 
   1481 nonnull_all
   1482 static int32_t parse_sshfp_rdata(
   1483   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1484 {
   1485   int32_t code;
   1486   const rdata_info_t *fields = type->rdata.fields;
   1487 
   1488   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1489     return code;
   1490   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   1491     return code;
   1492 
   1493   const uint8_t *fingerprint_type = rdata->octets;
   1494   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1495     return code;
   1496   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   1497     return code;
   1498 
   1499   const uint8_t *fingerprint = rdata->octets;
   1500   take(parser, token);
   1501   if ((code = parse_base16_sequence(parser, type, &fields[2], rdata, token)) < 0)
   1502     return code;
   1503 
   1504   // https://www.iana.org/assignments/dns-sshfp-rr-parameters
   1505   size_t fingerprint_size = (uintptr_t)rdata->octets - (uintptr_t)fingerprint;
   1506   if (unlikely(*fingerprint_type == 1 && fingerprint_size != 20))
   1507     SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s",
   1508                            "SHA1", NAME(type));
   1509   if (unlikely(*fingerprint_type == 2 && fingerprint_size != 32))
   1510     SEMANTIC_ERROR(parser, "Wrong fingerprint size for type %s in %s",
   1511                            "SHA256", NAME(type));
   1512 
   1513   return accept_rr(parser, type, rdata);
   1514 }
   1515 
   1516 nonnull_all
   1517 static int32_t check_ipseckey_rr(
   1518   parser_t *parser, const type_info_t *type, const rdata_t *rdata);
   1519 
   1520 nonnull_all
   1521 static int32_t parse_ipseckey_rdata(
   1522   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token);
   1523 
   1524 diagnostic_push()
   1525 gcc_diagnostic_ignored(missing-field-initializers)
   1526 clang_diagnostic_ignored(missing-field-initializers)
   1527 
   1528 static const rdata_info_t ipseckey_ipv4_rdata_fields[] = {
   1529   FIELD("precedence"),
   1530   FIELD("gateway type"),
   1531   FIELD("algorithm"),
   1532   FIELD("gateway"),
   1533   FIELD("public key")
   1534 };
   1535 
   1536 static const type_info_t ipseckey_ipv4[] = {
   1537   TYPE("IPSECKEY", ZONE_TYPE_IPSECKEY, ZONE_CLASS_IN, FIELDS(ipseckey_ipv4_rdata_fields),
   1538                    check_ipseckey_rr, parse_ipseckey_rdata),
   1539 };
   1540 
   1541 static const rdata_info_t ipseckey_ipv6_rdata_fields[] = {
   1542   FIELD("precedence"),
   1543   FIELD("gateway type"),
   1544   FIELD("algorithm"),
   1545   FIELD("gateway"),
   1546   FIELD("public key")
   1547 };
   1548 
   1549 static const type_info_t ipseckey_ipv6[] = {
   1550   TYPE("IPSECKEY", ZONE_TYPE_IPSECKEY, ZONE_CLASS_IN, FIELDS(ipseckey_ipv6_rdata_fields),
   1551                    check_ipseckey_rr, parse_ipseckey_rdata),
   1552 };
   1553 
   1554 diagnostic_pop()
   1555 
   1556 nonnull_all
   1557 static int32_t check_ipseckey_rr(
   1558   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1559 {
   1560   int32_t r;
   1561   size_t c = 0;
   1562   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1563   const uint8_t *o = parser->rdata->octets;
   1564   const type_info_t *t = type;
   1565   const rdata_info_t *f = type->rdata.fields;
   1566 
   1567   if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) ||
   1568       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   1569       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))))
   1570     return r;
   1571 
   1572   switch (parser->rdata->octets[1]) {
   1573     case 1: /* IPv4 address */
   1574       t = (const type_info_t *)ipseckey_ipv4;
   1575       f = ipseckey_ipv4_rdata_fields;
   1576       if ((r = check(&c, check_ip4(parser, t, &f[3], o+c, n-c))) < 0)
   1577         return r;
   1578       break;
   1579     case 2: /* IPv6 address */
   1580       t = (const type_info_t *)ipseckey_ipv6;
   1581       f = ipseckey_ipv6_rdata_fields;
   1582       if ((r = check(&c, check_ip6(parser, t, &f[3], o+c, n-c))) < 0)
   1583         return r;
   1584       break;
   1585     case 0: /* no gateway */
   1586       break;
   1587     case 3: /* domain name */
   1588       if ((r = check(&c, check_name(parser, t, &f[3], o+c, n-c))) < 0)
   1589         return r;
   1590       break;
   1591     default:
   1592       SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1593   }
   1594 
   1595   switch (parser->rdata->octets[2]) {
   1596     case 0:
   1597       if (c < n)
   1598         SYNTAX_ERROR(parser, "Trailing data in %s", NAME(t));
   1599       break;
   1600     default:
   1601       if (c >= n)
   1602         SYNTAX_ERROR(parser, "Missing %s in %s", NAME(&f[4]), NAME(t));
   1603       break;
   1604   }
   1605 
   1606   return accept_rr(parser, t, rdata);
   1607 }
   1608 
   1609 nonnull_all
   1610 static int32_t parse_ipseckey_rdata(
   1611   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1612 {
   1613   int32_t code;
   1614   const rdata_info_t *fields = type->rdata.fields;
   1615   uint8_t *octets = rdata->octets;
   1616 
   1617   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1618     return code;
   1619   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   1620     return code;
   1621   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1622     return code;
   1623   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   1624     return code;
   1625   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1626     return code;
   1627   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
   1628     return code;
   1629   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   1630     return code;
   1631 
   1632   switch (octets[1]) {
   1633     case 0: /* no gateway */
   1634       if (token->length != 1 || token->data[0] != '.')
   1635         SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type));
   1636       break;
   1637     case 1: /* IPv4 address */
   1638       type = (const type_info_t *)ipseckey_ipv4;
   1639       fields = type->rdata.fields;
   1640       if ((code = parse_ip4(parser, type, &fields[3], rdata, token)) < 0)
   1641         return code;
   1642       break;
   1643     case 2: /* IPv6 address */
   1644       type = (const type_info_t *)ipseckey_ipv6;
   1645       fields = type->rdata.fields;
   1646       if ((code = parse_ip6(parser, type, &fields[3], rdata, token)) < 0)
   1647         return code;
   1648       break;
   1649     case 3: /* domain name */
   1650       if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0)
   1651         return code;
   1652       break;
   1653     default:
   1654       SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type));
   1655   }
   1656 
   1657   take(parser, token);
   1658   switch (octets[2]) {
   1659     case 0:
   1660       if ((code = have_delimiter(parser, type, token)) < 0)
   1661         return code;
   1662       break;
   1663     default:
   1664       if ((code = parse_base64_sequence(parser, type, &fields[4], rdata, token)) < 0)
   1665         return code;
   1666       break;
   1667   }
   1668 
   1669   return accept_rr(parser, type, rdata);
   1670 }
   1671 
   1672 nonnull_all
   1673 static int32_t check_rrsig_rr(
   1674   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1675 {
   1676   int32_t r;
   1677   size_t c = 0;
   1678   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1679   const uint8_t *o = parser->rdata->octets;
   1680   const rdata_info_t *f = type->rdata.fields;
   1681 
   1682   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   1683       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   1684       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))) ||
   1685       (r = check(&c, check_ttl(parser, type, &f[3], o+c, n-c))) ||
   1686       (r = check(&c, check_int32(parser, type, &f[4], o+c, n-c))) ||
   1687       (r = check(&c, check_int32(parser, type, &f[5], o+c, n-c))) ||
   1688       (r = check(&c, check_int16(parser, type, &f[6], o+c, n-c))) ||
   1689       (r = check(&c, check_name(parser, type, &f[7], o+c, n-c))))
   1690     return r;
   1691 
   1692   if (c > n)
   1693     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1694   return accept_rr(parser, type, rdata);
   1695 }
   1696 
   1697 nonnull_all
   1698 static int32_t parse_rrsig_rdata(
   1699   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1700 {
   1701   int32_t code;
   1702   const rdata_info_t *fields = type->rdata.fields;
   1703 
   1704   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1705     return code;
   1706   if ((code = parse_type(parser, type, &fields[0], rdata, token)) < 0)
   1707     return code;
   1708   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1709     return code;
   1710   if ((code = parse_algorithm(parser, type, &fields[1], rdata, token)) < 0)
   1711     return code;
   1712   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1713     return code;
   1714   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
   1715     return code;
   1716   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   1717     return code;
   1718   if ((code = parse_ttl(parser, type, &fields[3], rdata, token)) < 0)
   1719     return code;
   1720   if ((code = take_contiguous(parser, type, &fields[4], token)) < 0)
   1721     return code;
   1722   if ((code = parse_time(parser, type, &fields[4], rdata, token)) < 0)
   1723     return code;
   1724   if ((code = take_contiguous(parser, type, &fields[5], token)) < 0)
   1725     return code;
   1726   if ((code = parse_time(parser, type, &fields[5], rdata, token)) < 0)
   1727     return code;
   1728   if ((code = take_contiguous(parser, type, &fields[6], token)) < 0)
   1729     return code;
   1730   if ((code = parse_int16(parser, type, &fields[6], rdata, token)) < 0)
   1731     return code;
   1732   if ((code = take_contiguous(parser, type, &fields[7], token)) < 0)
   1733     return code;
   1734   if ((code = parse_name(parser, type, &fields[7], rdata, token)) < 0)
   1735     return code;
   1736   take(parser, token);
   1737   if ((code = parse_base64_sequence(parser, type, &fields[8], rdata, token)) < 0)
   1738     return code;
   1739 
   1740   return accept_rr(parser, type, rdata);
   1741 }
   1742 
   1743 nonnull_all
   1744 static int32_t check_nsec_rr(
   1745   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1746 {
   1747   int32_t r;
   1748   size_t c = 0;
   1749   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1750   const uint8_t *o = parser->rdata->octets;
   1751   const rdata_info_t *f = type->rdata.fields;
   1752 
   1753   if ((r = check(&c, check_name(parser, type, &f[0], o, n))) ||
   1754       (r = check(&c, check_nsec(parser, type, &f[1], o+c, n-c))))
   1755     return r;
   1756 
   1757   if (c != n)
   1758     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1759   return accept_rr(parser, type, rdata);
   1760 }
   1761 
   1762 nonnull_all
   1763 static int32_t parse_nsec_rdata(
   1764   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1765 {
   1766   int32_t code;
   1767   const rdata_info_t *fields = type->rdata.fields;
   1768 
   1769   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1770     return code;
   1771   if ((code = parse_name(parser, type, &fields[0], rdata, token)) < 0)
   1772     return code;
   1773   take(parser, token);
   1774   if ((code = parse_nsec(parser, type, &fields[1], rdata, token)) < 0)
   1775     return code;
   1776 
   1777   return accept_rr(parser, type, rdata);
   1778 }
   1779 
   1780 nonnull_all
   1781 static int32_t check_dnskey_rr(
   1782   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1783 {
   1784   int32_t r;
   1785   size_t c = 0;
   1786   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1787   const uint8_t *o = parser->rdata->octets;
   1788   const rdata_info_t *f = type->rdata.fields;
   1789 
   1790   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   1791       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   1792       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))))
   1793     return r;
   1794 
   1795   if (c > n)
   1796     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1797   return accept_rr(parser, type, rdata);
   1798 }
   1799 
   1800 nonnull_all
   1801 static int32_t parse_dnskey_rdata(
   1802   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1803 {
   1804   int32_t code;
   1805   const rdata_info_t *fields = type->rdata.fields;
   1806 
   1807   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1808     return code;
   1809   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   1810     return code;
   1811   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1812     return code;
   1813   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   1814     return code;
   1815   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1816     return code;
   1817   if ((code = parse_algorithm(parser, type, &fields[2], rdata, token)) < 0)
   1818     return code;
   1819   take(parser, token);
   1820   if (!(token->length == 1 && (char)*token->data == '0')
   1821   &&  (code = parse_base64_sequence(parser, type, &fields[3], rdata, token)) < 0)
   1822     return code;
   1823 
   1824   return accept_rr(parser, type, rdata);
   1825 }
   1826 
   1827 nonnull_all
   1828 static int32_t check_dhcid_rr(
   1829   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1830 {
   1831   // RFC4701 section 3.1:
   1832   // 2-octet identifier type, 1-octet digest type, followed by one or more
   1833   // octets representing the actual identifier
   1834   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 4)
   1835     SEMANTIC_ERROR(parser, "Invalid %s", NAME(type));
   1836   return accept_rr(parser, type, rdata);
   1837 }
   1838 
   1839 nonnull_all
   1840 static int32_t parse_dhcid_rdata(
   1841   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1842 {
   1843   int32_t code;
   1844   const rdata_info_t *fields = type->rdata.fields;
   1845 
   1846   if ((code = parse_base64_sequence(parser, type, &fields[0], rdata, token)) < 0)
   1847     return code;
   1848 
   1849   return check_dhcid_rr(parser, type, rdata);
   1850 }
   1851 
   1852 nonnull_all
   1853 static int32_t check_nsec3_rr(
   1854   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1855 {
   1856   int32_t r;
   1857   size_t c = 0;
   1858   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1859   const uint8_t *o = parser->rdata->octets;
   1860   const rdata_info_t *f = type->rdata.fields;
   1861 
   1862   if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) ||
   1863       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   1864       (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) ||
   1865       (r = check(&c, check_string(parser, type, &f[3], o+c, n-c))) ||
   1866       (r = check(&c, check_string(parser, type, &f[4], o+c, n-c))) ||
   1867       (r = check(&c, check_nsec(parser, type, &f[5], o+c, n-c))))
   1868     return r;
   1869 
   1870   if (c != n)
   1871     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1872   return accept_rr(parser, type, rdata);
   1873 }
   1874 
   1875 nonnull_all
   1876 static int32_t parse_nsec3_rdata(
   1877   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1878 {
   1879   int32_t code;
   1880   const rdata_info_t *fields = type->rdata.fields;
   1881 
   1882   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1883     return code;
   1884   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   1885     return code;
   1886   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1887     return code;
   1888   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   1889     return code;
   1890   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1891     return code;
   1892   if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0)
   1893     return code;
   1894   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   1895     return code;
   1896   if ((code = parse_salt(parser, type, &fields[3], rdata, token)) < 0)
   1897     return code;
   1898   if ((code = take_contiguous(parser, type, &fields[4], token)) < 0)
   1899     return code;
   1900   if ((code = parse_base32(parser, type, &fields[4], rdata, token)) < 0)
   1901     return code;
   1902   take(parser, token);
   1903   if ((code = parse_nsec(parser, type, &fields[5], rdata, token)) < 0)
   1904     return code;
   1905 
   1906   return accept_rr(parser, type, rdata);
   1907 }
   1908 
   1909 nonnull_all
   1910 static int32_t check_nsec3param_rr(
   1911   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1912 {
   1913   int32_t r;
   1914   size_t c = 0;
   1915   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1916   const uint8_t *o = parser->rdata->octets;
   1917   const rdata_info_t *f = type->rdata.fields;
   1918 
   1919   if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) ||
   1920       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   1921       (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) ||
   1922       (r = check(&c, check_string(parser, type, &f[3], o+c, n-c))))
   1923     return r;
   1924 
   1925   if (c != n)
   1926     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1927   return accept_rr(parser, type, rdata);
   1928 }
   1929 
   1930 nonnull_all
   1931 static int32_t parse_nsec3param_rdata(
   1932   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1933 {
   1934   int32_t code;
   1935   const rdata_info_t *fields = type->rdata.fields;
   1936 
   1937   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1938     return code;
   1939   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   1940     return code;
   1941   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1942     return code;
   1943   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   1944     return code;
   1945   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1946     return code;
   1947   if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0)
   1948     return code;
   1949   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   1950     return code;
   1951   if ((code = parse_salt(parser, type, &fields[3], rdata, token)) < 0)
   1952     return code;
   1953   if ((code = take_delimiter(parser, type, token)) < 0)
   1954     return code;
   1955   return accept_rr(parser, type, rdata);
   1956 }
   1957 
   1958 nonnull_all
   1959 static int32_t check_tlsa_rr(
   1960   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   1961 {
   1962   int32_t r;
   1963   size_t c = 0;
   1964   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   1965   const uint8_t *o = parser->rdata->octets;
   1966   const rdata_info_t *f = type->rdata.fields;
   1967 
   1968   if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) ||
   1969       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   1970       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))))
   1971     return r;
   1972 
   1973   if (c >= n)
   1974     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   1975   return accept_rr(parser, type, rdata);
   1976 }
   1977 
   1978 nonnull_all
   1979 static int32_t parse_tlsa_rdata(
   1980   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   1981 {
   1982   int32_t code;
   1983   const rdata_info_t *fields = type->rdata.fields;
   1984 
   1985   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   1986     return code;
   1987   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   1988     return code;
   1989   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   1990     return code;
   1991   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   1992     return code;
   1993   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   1994     return code;
   1995   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
   1996     return code;
   1997   take(parser, token);
   1998   if ((code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0)
   1999     return code;
   2000 
   2001   return accept_rr(parser, type, rdata);
   2002 }
   2003 
   2004 nonnull_all
   2005 static int32_t check_hip_rr(
   2006   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2007 {
   2008   // FIXME: verify field lengths etc
   2009   return accept_rr(parser, type, rdata);
   2010 }
   2011 
   2012 nonnull_all
   2013 static int32_t parse_hip_rdata(
   2014   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2015 {
   2016   int32_t code;
   2017   const rdata_info_t *fields = type->rdata.fields;
   2018   uint8_t *octets = rdata->octets;
   2019 
   2020   // reserve octet for HIT length
   2021   rdata->octets += 1;
   2022 
   2023   // PK algorithm
   2024   if ((code = have_contiguous(parser, type, &fields[1], token)) < 0)
   2025     return code;
   2026   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   2027     return code;
   2028 
   2029   // reserve octets for PK length
   2030   rdata->octets += 2;
   2031 
   2032   // HIT
   2033   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   2034     return code;
   2035   if ((code = parse_base16(parser, type, &fields[3], rdata, token)) < 0)
   2036     return code;
   2037 
   2038   if ((rdata->octets - octets) > 255 + 4)
   2039     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type));
   2040   uint8_t hit_length = (uint8_t)((rdata->octets - octets) - 4);
   2041   octets[0] = hit_length;
   2042 
   2043   // Public Key
   2044   if ((code = take_contiguous(parser, type, &fields[4], token)) < 0)
   2045     return code;
   2046   if ((code = parse_base64(parser, type, &fields[4], rdata, token)) < 0)
   2047     return code;
   2048 
   2049   uint16_t pk_length = htobe16((uint16_t)(((rdata->octets - octets) - hit_length) - 4));
   2050   memcpy(&octets[2], &pk_length, sizeof(pk_length));
   2051 
   2052   take(parser, token);
   2053   while (is_contiguous(token)) {
   2054     if ((code = parse_name(parser, type, &fields[5], rdata, token)) < 0)
   2055       return code;
   2056     take(parser, token);
   2057   }
   2058 
   2059   if ((code = have_delimiter(parser, type, token)) < 0)
   2060     return code;
   2061   return accept_rr(parser, type, rdata);
   2062 }
   2063 
   2064 nonnull_all
   2065 static int32_t check_openpgpkey_rr(
   2066   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2067 {
   2068   // FIXME: as the RDATA contains a digest, it is likely we can make this
   2069   //        check stricter, at least, for known algorithms
   2070   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets < 4)
   2071     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2072   return accept_rr(parser, type, rdata);
   2073 }
   2074 
   2075 nonnull_all
   2076 static int32_t parse_openpgpkey_rdata(
   2077   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2078 {
   2079   int32_t code;
   2080   const rdata_info_t *fields = type->rdata.fields;
   2081 
   2082   if ((code = parse_base64_sequence(parser, type, &fields[0], rdata, token)) < 0)
   2083     return code;
   2084 
   2085   return accept_rr(parser, type, rdata);
   2086 }
   2087 
   2088 nonnull_all
   2089 static int32_t check_csync_rr(
   2090   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2091 {
   2092   int32_t r;
   2093   size_t c = 0;
   2094   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2095   const uint8_t *o = parser->rdata->octets;
   2096   const rdata_info_t *f = type->rdata.fields;
   2097 
   2098   if ((r = check(&c, check_int32(parser, type, &f[0], o, n))) ||
   2099       (r = check(&c, check_int16(parser, type, &f[1], o+c, n-c))) ||
   2100       (r = check(&c, check_nsec(parser, type, &f[2], o+c, n-c))))
   2101     return r;
   2102 
   2103   if (c != n)
   2104     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2105   return accept_rr(parser, type, rdata);
   2106 }
   2107 
   2108 nonnull_all
   2109 static int32_t parse_csync_rdata(
   2110   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2111 {
   2112   int32_t code;
   2113   const rdata_info_t *fields = type->rdata.fields;
   2114 
   2115   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2116     return code;
   2117   if ((code = parse_int32(parser, type, &fields[0], rdata, token)) < 0)
   2118     return code;
   2119   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2120     return code;
   2121   if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0)
   2122     return code;
   2123   take(parser, token);
   2124   if ((code = parse_nsec(parser, type, &fields[2], rdata, token)) < 0)
   2125     return code;
   2126 
   2127   return accept_rr(parser, type, rdata);
   2128 }
   2129 
   2130 nonnull_all
   2131 static int32_t check_zonemd_rr(
   2132   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2133 {
   2134   int32_t r;
   2135   size_t c = 0;
   2136   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2137   const uint8_t *o = parser->rdata->octets;
   2138   const rdata_info_t *f = type->rdata.fields;
   2139 
   2140   if ((r = check(&c, check_int32(parser, type, &f[0], o, n))) ||
   2141       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   2142       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))))
   2143     return r;
   2144 
   2145   const uint8_t digest_algorithm = parser->rdata->octets[5];
   2146   if ((digest_algorithm & 0x3) == digest_algorithm) {
   2147     // https://www.iana.org/assignments/dns-parameters#zonemd-hash-algorithms
   2148     static const uint8_t digest_sizes[4] = {
   2149       0,  // 0: Reserved
   2150       48, // 1: SHA-384
   2151       64, // 2: SHA-512
   2152       0   // 3: Unassigned
   2153     };
   2154 
   2155     const uint8_t digest_size = digest_sizes[ digest_algorithm ];
   2156     if (digest_size && n - 6 != digest_size)
   2157       SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type));
   2158   }
   2159 
   2160   return accept_rr(parser, type, rdata);
   2161 }
   2162 
   2163 nonnull_all
   2164 static int32_t parse_zonemd_rdata(
   2165   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2166 {
   2167   int32_t code;
   2168   const rdata_info_t *fields = type->rdata.fields;
   2169 
   2170   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2171     return code;
   2172   if ((code = parse_int32(parser, type, &fields[0], rdata, token)) < 0)
   2173     return code;
   2174   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2175     return code;
   2176   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   2177     return code;
   2178   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   2179     return code;
   2180   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
   2181     return code;
   2182   take(parser, token);
   2183   if ((code = parse_base16_sequence(parser, type, &fields[3], rdata, token)) < 0)
   2184     return code;
   2185 
   2186   const uint8_t digest_algorithm = parser->rdata->octets[5];
   2187   if ((digest_algorithm & 0x3) == digest_algorithm) {
   2188     // https://www.iana.org/assignments/dns-parameters#zonemd-hash-algorithms
   2189     static const uint8_t digest_sizes[4] = {
   2190       0,  // 0: Reserved
   2191       48, // 1: SHA-384
   2192       64, // 2: SHA-512
   2193       0   // 3: Unassigned
   2194     };
   2195 
   2196     const uint8_t digest_size = digest_sizes[ digest_algorithm ];
   2197     size_t length = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2198     if (digest_size && length - 6 != digest_size)
   2199       SEMANTIC_ERROR(parser, "Invalid digest in %s", NAME(type));
   2200   }
   2201 
   2202   return accept_rr(parser, type, rdata);
   2203 }
   2204 
   2205 nonnull_all
   2206 static int32_t check_svcb_rr(
   2207   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2208 {
   2209   //
   2210   // FIXME: implement checking parameters etc
   2211   //
   2212   // - check if all keys in mandatory exist
   2213   // - check if at least keys and key lengths are valid
   2214   //
   2215   // FIXME: implement reordering parameters in strict (primary) mode
   2216   // FIXME: note that when reordering or checking, rdata may not actually
   2217   //        contain valid parameters
   2218   //
   2219 
   2220   return accept_rr(parser, type, rdata);
   2221 }
   2222 
   2223 nonnull_all
   2224 static int32_t parse_svcb_rdata(
   2225   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2226 {
   2227   int32_t code;
   2228   const rdata_info_t *fields = type->rdata.fields;
   2229 
   2230   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2231     return code;
   2232   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   2233     return code;
   2234   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2235     return code;
   2236   if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0)
   2237     return code;
   2238   take(parser, token);
   2239   if ((code = parse_svc_params(parser, type, &fields[2], rdata, token)) < 0)
   2240     return code;
   2241 
   2242   return accept_rr(parser, type, rdata);
   2243 }
   2244 
   2245 nonnull_all
   2246 static int32_t check_https_rr(
   2247   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2248 {
   2249   //
   2250   // FIXME: incorporate fixes mentioned in check_svcb_rr
   2251   //
   2252 
   2253   return accept_rr(parser, type, rdata);
   2254 }
   2255 
   2256 nonnull_all
   2257 static int32_t parse_https_rdata(
   2258   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2259 {
   2260   int32_t code;
   2261   const rdata_info_t *fields = type->rdata.fields;
   2262 
   2263   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2264     return code;
   2265   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   2266     return code;
   2267   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2268     return code;
   2269   if ((code = parse_name(parser, type, &fields[1], rdata, token)) < 0)
   2270     return code;
   2271   take(parser, token);
   2272   if ((code = parse_svc_params(parser, type, &fields[2], rdata, token)) < 0)
   2273     return code;
   2274 
   2275   return accept_rr(parser, type, rdata);
   2276 }
   2277 
   2278 nonnull_all
   2279 static int32_t check_dsync_rr(
   2280   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2281 {
   2282   int32_t r;
   2283   size_t c = 0;
   2284   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2285   const uint8_t *o = parser->rdata->octets;
   2286   const rdata_info_t *f = type->rdata.fields;
   2287 
   2288   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   2289       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))) ||
   2290       (r = check(&c, check_int16(parser, type, &f[2], o+c, n-c))) ||
   2291       (r = check(&c, check_name(parser, type, &f[3], o+c, n-c))))
   2292     return r;
   2293 
   2294   const uint8_t dsync_scheme = o[2];
   2295   uint16_t dsync_type;
   2296   memcpy(&dsync_type, o, sizeof(dsync_type));
   2297   dsync_type = be16toh(dsync_type);
   2298   if (dsync_scheme == 1 && dsync_type != ZONE_TYPE_CDS
   2299                         && dsync_type != ZONE_TYPE_CSYNC)
   2300     SEMANTIC_ERROR(parser, "Wrong type for scheme 1 in %s", NAME(type));
   2301 
   2302   if (c > n)
   2303     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2304   return accept_rr(parser, type, rdata);
   2305 }
   2306 
   2307 nonnull_all
   2308 static int32_t parse_dsync_rdata(
   2309   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2310 {
   2311   int32_t code;
   2312   const rdata_info_t *fields = type->rdata.fields;
   2313 
   2314   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2315     return code;
   2316   if ((code = parse_type(parser, type, &fields[0], rdata, token)) < 0)
   2317     return code;
   2318   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2319     return code;
   2320   if ((code = parse_int8(parser, type, &fields[1], rdata, token)) < 0)
   2321     return code;
   2322   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   2323     return code;
   2324   if ((code = parse_int16(parser, type, &fields[2], rdata, token)) < 0)
   2325     return code;
   2326   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   2327     return code;
   2328   if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0)
   2329     return code;
   2330 
   2331   const uint8_t dsync_scheme = parser->rdata->octets[2];
   2332   uint16_t dsync_type;
   2333   memcpy(&dsync_type, parser->rdata->octets, sizeof(dsync_type));
   2334   dsync_type = be16toh(dsync_type);
   2335   if (dsync_scheme == 1 && dsync_type != ZONE_TYPE_CDS
   2336                         && dsync_type != ZONE_TYPE_CSYNC)
   2337     SEMANTIC_ERROR(parser, "Wrong type for scheme 1 in %s", NAME(type));
   2338 
   2339   return accept_rr(parser, type, rdata);
   2340 }
   2341 
   2342 nonnull_all
   2343 static int32_t check_nid_rr(
   2344   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2345 {
   2346   int32_t r;
   2347   size_t c = 0;
   2348   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2349   const uint8_t *o = parser->rdata->octets;
   2350   const rdata_info_t *f = type->rdata.fields;
   2351 
   2352   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   2353       (r = check(&c, check_ilnp64(parser, type, &f[1], o+c, n-c))))
   2354     return r;
   2355   if (c != n)
   2356     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2357   return accept_rr(parser, type, rdata);
   2358 }
   2359 
   2360 nonnull_all
   2361 static int32_t parse_nid_rdata(
   2362   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2363 {
   2364   int32_t code;
   2365   const rdata_info_t *fields = type->rdata.fields;
   2366 
   2367   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2368     return code;
   2369   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   2370     return code;
   2371   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2372     return code;
   2373   if ((code = parse_ilnp64(parser, type, &fields[1], rdata, token)) < 0)
   2374     return code;
   2375   if ((code = take_delimiter(parser, type, token)) < 0)
   2376     return code;
   2377   return accept_rr(parser, type, rdata);
   2378 }
   2379 
   2380 nonnull_all
   2381 static int32_t check_l32_rr(
   2382   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2383 {
   2384   int32_t r;
   2385   size_t c = 0;
   2386   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2387   const uint8_t *o = parser->rdata->octets;
   2388   const rdata_info_t *f = type->rdata.fields;
   2389 
   2390   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   2391       (r = check(&c, check_ip4(parser, type, &f[1], o+c, n-c))))
   2392     return r;
   2393 
   2394   if (c != n)
   2395     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2396   return accept_rr(parser, type, rdata);
   2397 }
   2398 
   2399 nonnull_all
   2400 static int32_t parse_l32_rdata(
   2401   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2402 {
   2403   int32_t code;
   2404   const rdata_info_t *fields = type->rdata.fields;
   2405 
   2406   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2407     return code;
   2408   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   2409     return code;
   2410   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2411     return code;
   2412   if ((code = parse_ip4(parser, type, &fields[1], rdata, token)) < 0)
   2413     return code;
   2414   if ((code = take_delimiter(parser, type, token)) < 0)
   2415     return code;
   2416   return accept_rr(parser, type, rdata);
   2417 }
   2418 
   2419 nonnull_all
   2420 static int32_t check_l64_rr(
   2421   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2422 {
   2423   int32_t r;
   2424   size_t c = 0;
   2425   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2426   const uint8_t *o = parser->rdata->octets;
   2427   const rdata_info_t *f = type->rdata.fields;
   2428 
   2429   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   2430       (r = check(&c, check_ilnp64(parser, type, &f[1], o+c, n-c))))
   2431     return r;
   2432   if (c != n)
   2433     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2434   return accept_rr(parser, type, rdata);
   2435 }
   2436 
   2437 nonnull_all
   2438 static int32_t parse_l64_rdata(
   2439   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2440 {
   2441   int32_t code;
   2442   const rdata_info_t *fields = type->rdata.fields;
   2443 
   2444   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2445     return code;
   2446   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   2447     return code;
   2448   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2449     return code;
   2450   if ((code = parse_ilnp64(parser, type, &fields[1], rdata, token)) < 0)
   2451     return code;
   2452   if ((code = take_delimiter(parser, type, token)) < 0)
   2453     return code;
   2454   return accept_rr(parser, type, rdata);
   2455 }
   2456 
   2457 nonnull_all
   2458 static int32_t check_eui48_rr(
   2459   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2460 {
   2461   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets != 6)
   2462     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2463   return accept_rr(parser, type, rdata);
   2464 }
   2465 
   2466 nonnull_all
   2467 static int32_t parse_eui48_rdata(
   2468   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2469 {
   2470   int32_t code;
   2471   const rdata_info_t *fields = type->rdata.fields;
   2472 
   2473   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2474     return code;
   2475   if ((code = parse_eui48(parser, type, &fields[0], rdata, token)) < 0)
   2476     return code;
   2477   if ((code = take_delimiter(parser, type, token)) < 0)
   2478     return code;
   2479   return accept_rr(parser, type, rdata);
   2480 }
   2481 
   2482 nonnull_all
   2483 static int32_t check_eui64_rr(
   2484   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2485 {
   2486   if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets != 8)
   2487     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2488   return accept_rr(parser, type, rdata);
   2489 }
   2490 
   2491 nonnull_all
   2492 static int32_t parse_eui64_rdata(
   2493   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2494 {
   2495   int32_t code;
   2496   const rdata_info_t *fields = type->rdata.fields;
   2497 
   2498   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2499     return code;
   2500   if ((code = parse_eui64(parser, type, &fields[0], rdata, token)) < 0)
   2501     return code;
   2502   if ((code = take_delimiter(parser, type, token)) < 0)
   2503     return code;
   2504   return accept_rr(parser, type, rdata);
   2505 }
   2506 
   2507 nonnull_all
   2508 static int32_t check_uri_rr(
   2509   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2510 {
   2511   int32_t r;
   2512   size_t c = 0;
   2513   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2514   const uint8_t *o = parser->rdata->octets;
   2515   const rdata_info_t *f = type->rdata.fields;
   2516 
   2517   if ((r = check(&c, check_int16(parser, type, &f[0], o, n))) ||
   2518       (r = check(&c, check_int16(parser, type, &f[1], o+c, n-c))))
   2519     return r;
   2520   if (c >= n)
   2521     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2522   return accept_rr(parser, type, rdata);
   2523 }
   2524 
   2525 nonnull_all
   2526 static int32_t parse_uri_rdata(
   2527   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2528 {
   2529   int32_t code;
   2530   const rdata_info_t *fields = type->rdata.fields;
   2531 
   2532   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2533     return code;
   2534   if ((code = parse_int16(parser, type, &fields[0], rdata, token)) < 0)
   2535     return code;
   2536   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2537     return code;
   2538   if ((code = parse_int16(parser, type, &fields[1], rdata, token)) < 0)
   2539     return code;
   2540   if ((code = take_quoted(parser, type, &fields[2], token)) < 0)
   2541     return code;
   2542   if ((code = parse_text(parser, type, &fields[2], rdata, token)) < 0)
   2543     return code;
   2544   if ((code = take_delimiter(parser, type, token)) < 0)
   2545     return code;
   2546   return accept_rr(parser, type, rdata);
   2547 }
   2548 
   2549 nonnull_all
   2550 static int32_t check_caa_rr(
   2551   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2552 {
   2553   int32_t r;
   2554   size_t c = 0;
   2555   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2556   const uint8_t *o = parser->rdata->octets;
   2557   const rdata_info_t *f = type->rdata.fields;
   2558 
   2559   if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) ||
   2560       (r = check(&c, check_int8(parser, type, &f[1], o+c, n-c))))
   2561     return r;
   2562   if (c >= n)
   2563     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2564   return accept_rr(parser, type, rdata);
   2565 }
   2566 
   2567 nonnull_all
   2568 static int32_t parse_caa_rdata(
   2569   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2570 {
   2571   int32_t code;
   2572   const rdata_info_t *fields = type->rdata.fields;
   2573 
   2574   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2575     return code;
   2576   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   2577     return code;
   2578   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2579     return code;
   2580   if ((code = parse_caa_tag(parser, type, &fields[1], rdata, token)) < 0)
   2581     return code;
   2582   if ((code = take_quoted_or_contiguous(parser, type, &fields[2], token)) < 0)
   2583     return code;
   2584   if ((code = parse_text(parser, type, &fields[2], rdata, token)) < 0)
   2585     return code;
   2586   if ((code = take_delimiter(parser, type, token)) < 0)
   2587     return code;
   2588   return accept_rr(parser, type, rdata);
   2589 }
   2590 
   2591 nonnull_all
   2592 static int32_t check_doa_rr(
   2593   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2594 {
   2595   int32_t r;
   2596   size_t c = 0;
   2597   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2598   const uint8_t *o = parser->rdata->octets;
   2599   const rdata_info_t *f = type->rdata.fields;
   2600 
   2601   if ((r = check(&c, check_int32(parser, type, &f[0], o, n))) ||
   2602       (r = check(&c, check_int32(parser, type, &f[1], o+c, n-c))) ||
   2603       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))) ||
   2604       (r = check(&c, check_string(parser, type, &f[3], o+c, n-c))))
   2605     return r;
   2606   if (c > n)
   2607     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2608   return accept_rr(parser, type, rdata);
   2609 }
   2610 
   2611 nonnull_all
   2612 static int32_t parse_doa_rdata(
   2613   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2614 {
   2615   int32_t code;
   2616   const rdata_info_t *fields = type->rdata.fields;
   2617 
   2618   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2619     return code;
   2620   if ((code = parse_int32(parser, type, &fields[0], rdata, token)) < 0)
   2621     return code;
   2622   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2623     return code;
   2624   if ((code = parse_int32(parser, type, &fields[1], rdata, token)) < 0)
   2625     return code;
   2626   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   2627     return code;
   2628   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
   2629     return code;
   2630   if ((code = take_quoted_or_contiguous(parser, type, &fields[3], token)) < 0)
   2631     return code;
   2632   if ((code = parse_string(parser, type, &fields[3], rdata, token)) < 0)
   2633     return code;
   2634   take(parser, token);
   2635   if (!(token->length == 1 && ((char)*token->data == '0' || (char)*token->data == '-'))
   2636   &&  (code = parse_base64_sequence(parser, type, &fields[4], rdata, token)) < 0)
   2637     return code;
   2638   return accept_rr(parser, type, rdata);
   2639 }
   2640 
   2641 nonnull_all
   2642 static int32_t check_amtrelay_rr(
   2643   parser_t *parser, const type_info_t *type, const rdata_t *rdata);
   2644 
   2645 nonnull_all
   2646 static int32_t parse_amtrelay_rdata(
   2647   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token);
   2648 
   2649 diagnostic_push()
   2650 gcc_diagnostic_ignored(missing-field-initializers)
   2651 clang_diagnostic_ignored(missing-field-initializers)
   2652 
   2653 static const rdata_info_t amtrelay_ipv4_rdata_fields[] = {
   2654   FIELD("precedence"),
   2655   FIELD("discovery optional"),
   2656   FIELD("type"),
   2657   FIELD("relay")
   2658 };
   2659 
   2660 static const type_info_t amtrelay_ipv4[] = {
   2661   TYPE("AMTRELAY", ZONE_TYPE_AMTRELAY, ZONE_CLASS_IN, FIELDS(amtrelay_ipv4_rdata_fields),
   2662                    check_amtrelay_rr, parse_amtrelay_rdata),
   2663 };
   2664 
   2665 static const rdata_info_t amtrelay_ipv6_rdata_fields[] = {
   2666   FIELD("precedence"),
   2667   FIELD("discovery optional"),
   2668   FIELD("type"),
   2669   FIELD("relay")
   2670 };
   2671 
   2672 static const type_info_t amtrelay_ipv6[] = {
   2673   TYPE("AMTRELAY", ZONE_TYPE_AMTRELAY, ZONE_CLASS_IN, FIELDS(amtrelay_ipv6_rdata_fields),
   2674                    check_amtrelay_rr, parse_amtrelay_rdata),
   2675 };
   2676 
   2677 diagnostic_pop()
   2678 
   2679 nonnull_all
   2680 static int32_t check_amtrelay_rr(
   2681   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2682 {
   2683   int32_t r;
   2684   size_t c = 0;
   2685   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2686   const uint8_t *o = parser->rdata->octets;
   2687   const type_info_t *t = type;
   2688   const rdata_info_t *f = type->rdata.fields;
   2689 
   2690   if ((r = check(&c, check_int8(parser, type, &f[0], o, n))) ||
   2691       (r = check(&c, check_int8(parser, type, &f[2], o+c, n-c))))
   2692     return r;
   2693 
   2694   switch (parser->rdata->octets[1] & 0x7f) {
   2695     case 1: /* IPv4 address */
   2696       t = (const type_info_t *)amtrelay_ipv4;
   2697       f = amtrelay_ipv4_rdata_fields;
   2698       if ((r = check(&c, check_ip4(parser, t, &f[3], o+c, n-c))) < 0)
   2699         return r;
   2700       break;
   2701     case 2: /* IPv6 address */
   2702       t = (const type_info_t *)amtrelay_ipv6;
   2703       f = amtrelay_ipv6_rdata_fields;
   2704       if ((r = check(&c, check_ip6(parser, t, &f[3], o+c, n-c))) < 0)
   2705         return r;
   2706       break;
   2707     case 0: /* no gateway */
   2708       break;
   2709     case 3: /* domain name */
   2710       if ((r = check(&c, check_name(parser, t, &f[3], o+c, n-c))) < 0)
   2711         return r;
   2712       break;
   2713     default:
   2714       SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2715   }
   2716   if (c < n)
   2717     SYNTAX_ERROR(parser, "Trailing data in %s", NAME(t));
   2718   return accept_rr(parser, t, rdata);
   2719 }
   2720 
   2721 nonnull_all
   2722 static int32_t parse_amtrelay_rdata(
   2723   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2724 {
   2725   int32_t code;
   2726   const rdata_info_t *fields = type->rdata.fields;
   2727   uint8_t *octets = rdata->octets;
   2728   uint8_t D;
   2729 
   2730   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2731     return code;
   2732   if ((code = parse_int8(parser, type, &fields[0], rdata, token)) < 0)
   2733     return code;
   2734 
   2735   if ((code = take_contiguous(parser, type, &fields[1], token)) < 0)
   2736     return code;
   2737   if (token->length != 1)
   2738     SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type));
   2739   switch((char)*token->data) {
   2740     case '0':
   2741       D = 0x00;
   2742       break;
   2743     case '1':
   2744       D = 0x80;
   2745       break;
   2746     default :
   2747       SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(type));
   2748   }
   2749 
   2750   if ((code = take_contiguous(parser, type, &fields[2], token)) < 0)
   2751     return code;
   2752   if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0)
   2753     return code;
   2754 
   2755   if ((code = take_contiguous(parser, type, &fields[3], token)) < 0)
   2756     return code;
   2757   switch (octets[1]) {
   2758     case 0:
   2759       /* no gateway requires a '.' as the relay in presentation format
   2760        * without parsing it into wireformat rdata */
   2761       if (!(token->length == 1 && *token->data == '.'))
   2762         SYNTAX_ERROR(parser, "Invalid %s in %s, the no gateway type (type 0) of AMTRELAY requires the relay field to have '.' in it", NAME(&fields[3]), NAME(type));
   2763       break;
   2764     case 1: /* IPv4 address */
   2765       type = (const type_info_t *)amtrelay_ipv4;
   2766       fields = type->rdata.fields;
   2767       if ((code = parse_ip4(parser, type, &fields[3], rdata, token)) < 0)
   2768         return code;
   2769       break;
   2770     case 2: /* IPv6 address */
   2771       type = (const type_info_t *)amtrelay_ipv6;
   2772       fields = type->rdata.fields;
   2773       if ((code = parse_ip6(parser, type, &fields[3], rdata, token)) < 0)
   2774         return code;
   2775       break;
   2776     case 3: /* domain name */
   2777       if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0)
   2778         return code;
   2779       break;
   2780     default:
   2781       SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type));
   2782   }
   2783   octets[1] |= D;
   2784   if ((code = take_delimiter(parser, type, token)) < 0)
   2785     return code;
   2786   return accept_rr(parser, type, rdata);
   2787 }
   2788 
   2789 nonnull_all
   2790 static int32_t check_ipn_rr(
   2791   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2792 {
   2793   int32_t r;
   2794   size_t c = 0;
   2795   const size_t n = (uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets;
   2796   const uint8_t *o = parser->rdata->octets;
   2797   const rdata_info_t *f = type->rdata.fields;
   2798 
   2799   if ((r = check(&c, check_int64(parser, type, &f[0], o, n))))
   2800     return r;
   2801   if (c > n)
   2802     SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
   2803   return accept_rr(parser, type, rdata);
   2804 }
   2805 
   2806 nonnull_all
   2807 static int32_t parse_ipn_rdata(
   2808   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2809 {
   2810   int32_t code;
   2811   const rdata_info_t *fields = type->rdata.fields;
   2812   token_t left, right;
   2813 
   2814   /* draft-johnson-dns-ipn-cla-07 Section 3.1. IPN:
   2815    *   Presentation format for these resource records are either a 64 bit
   2816    *   unsigned decimal integer, or two 32 bit unsigned decimal integers
   2817    *   delimited by a period with the most significant 32 bits first and least
   2818    *   significant 32 bits last.
   2819    */
   2820   if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
   2821     return code;
   2822   if (!(right.data = memchr(token->data, '.', token->length))) {
   2823     if ((code = parse_int64(parser, type, &fields[0], rdata, token)) < 0)
   2824       return code;
   2825     if ((code = take_delimiter(parser, type, token)) < 0)
   2826       return code;
   2827     return accept_rr(parser, type, rdata);
   2828   }
   2829   left.code = token->code;
   2830   left.data = token->data;
   2831   left.length = (size_t)(right.data - token->data);
   2832   right.code = token->code;
   2833   right.data += 1;
   2834   right.length = token->length - left.length - 1;
   2835   if ((code = parse_int32(parser, type, &fields[0], rdata, &left)) < 0)
   2836 	  return code;
   2837   if ((code = parse_int32(parser, type, &fields[0], rdata, &right)) < 0)
   2838 	  return code;
   2839   if ((code = take_delimiter(parser, type, token)) < 0)
   2840     return code;
   2841   return accept_rr(parser, type, rdata);
   2842 }
   2843 
   2844 nonnull_all
   2845 static int32_t check_generic_rr(
   2846   parser_t *parser, const type_info_t *type, const rdata_t *rdata)
   2847 {
   2848   return accept_rr(parser, type, rdata);
   2849 }
   2850 
   2851 nonnull_all
   2852 static int32_t parse_generic_rdata(
   2853   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2854 {
   2855   int32_t code;
   2856   uint16_t rdlength;
   2857   static const rdata_info_t fields[] = {
   2858     FIELD("rdlength"),
   2859     FIELD("rdata")
   2860   };
   2861 
   2862   // discard '\#'
   2863   if ((code = take_contiguous(parser, type, &fields[0], token)) < 0)
   2864     return code;
   2865   if (!scan_int16(token->data, token->length, &rdlength))
   2866     SYNTAX_ERROR(parser, "Invalid RDLENGTH in %s", NAME(type));
   2867 
   2868   take(parser, token);
   2869   if (is_contiguous(token)) {
   2870     struct base16_state state = { .eof = 0, .bytes = 0, .carry = 0 };
   2871 
   2872     do {
   2873       size_t length = token->length + 1 / 2;
   2874       if (length > (uintptr_t)rdata->limit - (uintptr_t)rdata->octets)
   2875         SYNTAX_ERROR(parser, "Invalid RDATA in %s", NAME(type));
   2876       if (!base16_stream_decode(&state, token->data, token->length, rdata->octets, &length))
   2877         SYNTAX_ERROR(parser, "Invalid RDATA in %s", NAME(type));
   2878       rdata->octets += length;
   2879       take(parser, token);
   2880     } while (is_contiguous(token));
   2881 
   2882     if (state.bytes)
   2883       *rdata->octets++ = state.carry;
   2884   }
   2885 
   2886   if ((code = have_delimiter(parser, type, token)) < 0)
   2887     return code;
   2888   if (rdata->octets - parser->rdata->octets != rdlength)
   2889     SYNTAX_ERROR(parser, "Invalid RDATA in %s", NAME(type));
   2890   return type->check(parser, type, rdata);
   2891 }
   2892 
   2893 nonnull_all
   2894 static int32_t parse_unknown_rdata(
   2895   parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
   2896 {
   2897   (void)type;
   2898   (void)rdata;
   2899   (void)token;
   2900   SYNTAX_ERROR(parser, "Unknown record type");
   2901 }
   2902 
   2903 diagnostic_push()
   2904 gcc_diagnostic_ignored(missing-field-initializers)
   2905 clang_diagnostic_ignored(missing-field-initializers)
   2906 
   2907 static const class_info_t classes[] = {
   2908   UNKNOWN_CLASS(0),
   2909   CLASS("IN", ZONE_CLASS_IN),
   2910   CLASS("CS", ZONE_CLASS_CS),
   2911   CLASS("CH", ZONE_CLASS_CH),
   2912   CLASS("HS", ZONE_CLASS_HS)
   2913 };
   2914 
   2915 static const rdata_info_t a_rdata_fields[] = {
   2916   FIELD("address")
   2917 };
   2918 
   2919 static const rdata_info_t ns_rdata_fields[] = {
   2920   FIELD("host")
   2921 };
   2922 
   2923 static const rdata_info_t md_rdata_fields[] = {
   2924   FIELD("madname")
   2925 };
   2926 
   2927 static const rdata_info_t mf_rdata_fields[] = {
   2928   FIELD("madname")
   2929 };
   2930 
   2931 static const rdata_info_t cname_rdata_fields[] = {
   2932   FIELD("host")
   2933 };
   2934 
   2935 static const rdata_info_t soa_rdata_fields[] = {
   2936   FIELD("primary"),
   2937   FIELD("mailbox"),
   2938   FIELD("serial"),
   2939   FIELD("refresh"),
   2940   FIELD("retry"),
   2941   FIELD("expire"),
   2942   FIELD("minimum")
   2943 };
   2944 
   2945 static const rdata_info_t mb_rdata_fields[] = {
   2946   FIELD("madname")
   2947 };
   2948 
   2949 static const rdata_info_t mg_rdata_fields[] = {
   2950   FIELD("mgmname")
   2951 };
   2952 
   2953 static const rdata_info_t mr_rdata_fields[] = {
   2954   FIELD("newname")
   2955 };
   2956 
   2957 static const rdata_info_t ptr_rdata_fields[] = {
   2958   FIELD("ptrdname")
   2959 };
   2960 
   2961 static const rdata_info_t hinfo_rdata_fields[] = {
   2962   FIELD("cpu"),
   2963   FIELD("os")
   2964 };
   2965 
   2966 static const rdata_info_t minfo_rdata_fields[] = {
   2967   FIELD("rmailbx"),
   2968   FIELD("emailbx")
   2969 };
   2970 
   2971 static const rdata_info_t null_rdata_fields[] = {
   2972   FIELD("anything")
   2973 };
   2974 
   2975 static const rdata_info_t wks_rdata_fields[] = {
   2976   FIELD("address"),
   2977   FIELD("protocol"),
   2978   FIELD("bitmap")
   2979 };
   2980 
   2981 static const rdata_info_t mx_rdata_fields[] = {
   2982   FIELD("priority"),
   2983   FIELD("hostname")
   2984 };
   2985 
   2986 static const rdata_info_t txt_rdata_fields[] = {
   2987   FIELD("text")
   2988 };
   2989 
   2990 static const rdata_info_t rp_rdata_fields[] = {
   2991   FIELD("mailbox"),
   2992   FIELD("text")
   2993 };
   2994 
   2995 static const rdata_info_t afsdb_rdata_fields[] = {
   2996   FIELD("subtype"),
   2997   FIELD("hostname")
   2998 };
   2999 
   3000 static const rdata_info_t x25_rdata_fields[] = {
   3001   FIELD("address")
   3002 };
   3003 
   3004 static const rdata_info_t isdn_rdata_fields[] = {
   3005   FIELD("address"),
   3006   FIELD("subaddress")
   3007 };
   3008 
   3009 static const rdata_info_t rt_rdata_fields[] = {
   3010   FIELD("preference"),
   3011   FIELD("hostname")
   3012 };
   3013 
   3014 static const rdata_info_t nsap_rdata_fields[] = {
   3015   FIELD("address")
   3016 };
   3017 
   3018 static const rdata_info_t nsap_ptr_rdata_fields[] = {
   3019   FIELD("hostname")
   3020 };
   3021 
   3022 static const rdata_info_t key_rdata_fields[] = {
   3023   FIELD("flags"),
   3024   FIELD("protocol"),
   3025   FIELD("algorithm"),
   3026   FIELD("publickey")
   3027 };
   3028 
   3029 static const rdata_info_t px_rdata_fields[] = {
   3030   FIELD("preference"),
   3031   FIELD("map822"),
   3032   FIELD("mapx400")
   3033 };
   3034 
   3035 static const rdata_info_t gpos_rdata_fields[] = {
   3036   FIELD("latitude"),
   3037   FIELD("longitude"),
   3038   FIELD("altitude")
   3039 };
   3040 
   3041 static const rdata_info_t aaaa_rdata_fields[] = {
   3042   FIELD("address")
   3043 };
   3044 
   3045 static const rdata_info_t loc_rdata_fields[] = {
   3046   FIELD("version"),
   3047   FIELD("size"),
   3048   FIELD("horizontal precision"),
   3049   FIELD("vertical precision"),
   3050   FIELD("latitude"),
   3051   FIELD("longitude"),
   3052   FIELD("altitude")
   3053 };
   3054 
   3055 static const rdata_info_t nxt_rdata_fields[] = {
   3056   FIELD("next domain name"),
   3057   FIELD("type bit map")
   3058 };
   3059 
   3060 static const rdata_info_t eid_rdata_fields[] = {
   3061   FIELD("end point identifier")
   3062 };
   3063 
   3064 static const rdata_info_t nimloc_rdata_fields[] = {
   3065   FIELD("nimrod locator")
   3066 };
   3067 
   3068 static const rdata_info_t srv_rdata_fields[] = {
   3069   FIELD("priority"),
   3070   FIELD("weight"),
   3071   FIELD("port"),
   3072   FIELD("target")
   3073 };
   3074 
   3075 static const rdata_info_t atma_rdata_fields[] = {
   3076   FIELD("address")
   3077 };
   3078 
   3079 static const rdata_info_t naptr_rdata_fields[] = {
   3080   FIELD("order"),
   3081   FIELD("preference"),
   3082   FIELD("flags"),
   3083   FIELD("services"),
   3084   FIELD("regex"),
   3085   FIELD("replacement"),
   3086 };
   3087 
   3088 static const rdata_info_t kx_rdata_fields[] = {
   3089   FIELD("preference"),
   3090   FIELD("exchanger")
   3091 };
   3092 
   3093 static const rdata_info_t sig_rdata_fields[] = {
   3094   FIELD("sigtype"),
   3095   FIELD("algorithm"),
   3096   FIELD("labels"),
   3097   FIELD("origttl"),
   3098   FIELD("expire"),
   3099   FIELD("inception"),
   3100   FIELD("keytag"),
   3101   FIELD("signer"),
   3102   FIELD("signature")
   3103 };
   3104 
   3105 static const rdata_info_t cert_rdata_fields[] = {
   3106   FIELD("type"),
   3107   FIELD("key tag"),
   3108   FIELD("algorithm"),
   3109   FIELD("certificate")
   3110 };
   3111 
   3112 static const rdata_info_t dname_rdata_fields[] = {
   3113   FIELD("source")
   3114 };
   3115 
   3116 static const rdata_info_t sink_rdata_fields[] = {
   3117   FIELD("coding"),
   3118   FIELD("subcoding"),
   3119   FIELD("data")
   3120 };
   3121 
   3122 static const rdata_info_t apl_rdata_fields[] = {
   3123   FIELD("prefix")
   3124 };
   3125 
   3126 static const rdata_info_t ds_rdata_fields[] = {
   3127   FIELD("keytag"),
   3128   FIELD("algorithm"),
   3129   FIELD("digtype"),
   3130   FIELD("digest")
   3131 };
   3132 
   3133 static const rdata_info_t sshfp_rdata_fields[] = {
   3134   FIELD("algorithm"),
   3135   FIELD("ftype"),
   3136   FIELD("fingerprint")
   3137 };
   3138 
   3139 // IPSECKEY is different because the rdata depends on the algorithm
   3140 static const rdata_info_t ipseckey_rdata_fields[] = {
   3141   FIELD("precedence"),
   3142   FIELD("gateway type"),
   3143   FIELD("algorithm"),
   3144   FIELD("gateway"),
   3145   FIELD("public key")
   3146 };
   3147 
   3148 static const rdata_info_t rrsig_rdata_fields[] = {
   3149   FIELD("rrtype"),
   3150   FIELD("algorithm"),
   3151   FIELD("labels"),
   3152   FIELD("origttl"),
   3153   FIELD("expire"),
   3154   FIELD("inception"),
   3155   FIELD("keytag"),
   3156   FIELD("signer"),
   3157   FIELD("signature")
   3158 };
   3159 
   3160 static const rdata_info_t nsec_rdata_fields[] = {
   3161   FIELD("next"),
   3162   FIELD("types")
   3163 };
   3164 
   3165 static const rdata_info_t dnskey_rdata_fields[] = {
   3166   FIELD("flags"),
   3167   FIELD("protocol"),
   3168   FIELD("algorithm"),
   3169   FIELD("publickey")
   3170 };
   3171 
   3172 static const rdata_info_t dhcid_rdata_fields[] = {
   3173   FIELD("dhcpinfo")
   3174 };
   3175 
   3176 static const rdata_info_t nsec3_rdata_fields[] = {
   3177   FIELD("algorithm"),
   3178   FIELD("flags"),
   3179   FIELD("iterations"),
   3180   FIELD("salt"),
   3181   FIELD("next"),
   3182   FIELD("types")
   3183 };
   3184 
   3185 static const rdata_info_t nsec3param_rdata_fields[] = {
   3186   FIELD("algorithm"),
   3187   FIELD("flags"),
   3188   FIELD("iterations"),
   3189   FIELD("salt")
   3190 };
   3191 
   3192 static const rdata_info_t tlsa_rdata_fields[] = {
   3193   FIELD("usage"),
   3194   FIELD("selector"),
   3195   FIELD("matching type"),
   3196   FIELD("certificate association data")
   3197 };
   3198 
   3199 static const rdata_info_t smimea_rdata_fields[] = {
   3200   FIELD("usage"),
   3201   FIELD("selector"),
   3202   FIELD("matching type"),
   3203   FIELD("certificate association data")
   3204 };
   3205 
   3206 static const rdata_info_t cds_rdata_fields[] = {
   3207   FIELD("keytag"),
   3208   FIELD("algorithm"),
   3209   FIELD("digtype"),
   3210   FIELD("digest")
   3211 };
   3212 
   3213 static const rdata_info_t cdnskey_rdata_fields[] = {
   3214   FIELD("flags"),
   3215   FIELD("protocol"),
   3216   FIELD("algorithm"),
   3217   FIELD("publickey")
   3218 };
   3219 
   3220 static const rdata_info_t hip_rdata_fields[] = {
   3221   FIELD("HIT length"),
   3222   FIELD("PK algorithm"),
   3223   FIELD("PK length"),
   3224   FIELD("HIT"),
   3225   FIELD("Public Key"),
   3226   FIELD("Rendezvous Servers")
   3227 };
   3228 
   3229 // https://www.iana.org/assignments/dns-parameters/NINFO/ninfo-completed-template
   3230 static const rdata_info_t ninfo_rdata_fields[] = {
   3231   FIELD("text")
   3232 };
   3233 
   3234 // https://www.iana.org/assignments/dns-parameters/RKEY/rkey-completed-template
   3235 static const rdata_info_t rkey_rdata_fields[] = {
   3236   FIELD("flags"),
   3237   FIELD("protocol"),
   3238   FIELD("algorithm"),
   3239   FIELD("publickey")
   3240 };
   3241 
   3242 // https://www.iana.org/assignments/dns-parameters/TALINK/talink-completed-template
   3243 static const rdata_info_t talink_rdata_fields[] = {
   3244   FIELD("start or previous"),
   3245   FIELD("end or next")
   3246 };
   3247 
   3248 static const rdata_info_t openpgpkey_rdata_fields[] = {
   3249   FIELD("key")
   3250 };
   3251 
   3252 static const rdata_info_t csync_rdata_fields[] = {
   3253   FIELD("serial"),
   3254   FIELD("flags"),
   3255   FIELD("types")
   3256 };
   3257 
   3258 static const rdata_info_t zonemd_rdata_fields[] = {
   3259   FIELD("serial"),
   3260   FIELD("scheme"),
   3261   FIELD("algorithm"),
   3262   FIELD("digest"),
   3263 };
   3264 
   3265 static const rdata_info_t svcb_rdata_fields[] = {
   3266   FIELD("priority"),
   3267   FIELD("target"),
   3268   FIELD("params")
   3269 };
   3270 
   3271 static const rdata_info_t https_rdata_fields[] = {
   3272   FIELD("priority"),
   3273   FIELD("target"),
   3274   FIELD("params")
   3275 };
   3276 
   3277 static const rdata_info_t dsync_rdata_fields[] = {
   3278   FIELD("rrtype"),
   3279   FIELD("scheme"),
   3280   FIELD("port"),
   3281   FIELD("target")
   3282 };
   3283 
   3284 static const rdata_info_t spf_rdata_fields[] = {
   3285   FIELD("text")
   3286 };
   3287 
   3288 static const rdata_info_t nid_rdata_fields[] = {
   3289   FIELD("preference"),
   3290   FIELD("nodeid")
   3291 };
   3292 
   3293 // RFC6742 specifies the syntax for the locator is compatible with the syntax
   3294 // for IPv4 addresses, but then proceeds to provide an example with leading
   3295 // zeroes. The example is corrected in the errata.
   3296 static const rdata_info_t l32_rdata_fields[] = {
   3297   FIELD("preference"),
   3298   FIELD("locator")
   3299 };
   3300 
   3301 static const rdata_info_t l64_rdata_fields[] = {
   3302   FIELD("preference"),
   3303   FIELD("locator")
   3304 };
   3305 
   3306 static const rdata_info_t lp_rdata_fields[] = {
   3307   FIELD("preference"),
   3308   FIELD("pointer")
   3309 };
   3310 
   3311 static const rdata_info_t eui48_rdata_fields[] = {
   3312   FIELD("address")
   3313 };
   3314 
   3315 static const rdata_info_t eui64_rdata_fields[] = {
   3316   FIELD("address")
   3317 };
   3318 
   3319 static const rdata_info_t uri_rdata_fields[] = {
   3320   FIELD("priority"),
   3321   FIELD("weight"),
   3322   FIELD("target")
   3323 };
   3324 
   3325 static const rdata_info_t caa_rdata_fields[] = {
   3326   FIELD("flags"),
   3327   FIELD("tag"),
   3328   FIELD("value")
   3329 };
   3330 
   3331 // https://www.iana.org/assignments/dns-parameters/AVC/avc-completed-template
   3332 static const rdata_info_t avc_rdata_fields[] = {
   3333   FIELD("text")
   3334 };
   3335 
   3336 // draft-durand-doa-over-dns-02
   3337 static const rdata_info_t doa_rdata_fields[] = {
   3338   FIELD("enterprise"),
   3339   FIELD("type"),
   3340   FIELD("location"),
   3341   FIELD("media type"),
   3342   FIELD("data")
   3343 };
   3344 
   3345 // RFC 8777
   3346 // AMTRELAY is different because the rdata depends on the type
   3347 static const rdata_info_t amtrelay_rdata_fields[] = {
   3348   FIELD("precedence"),
   3349   FIELD("discovery optional"),
   3350   FIELD("type"),
   3351   FIELD("relay"),
   3352 };
   3353 
   3354 
   3355 // RFC 9606
   3356 static const rdata_info_t resinfo_rdata_fields[] = {
   3357   FIELD("text")
   3358 };
   3359 
   3360 // https://www.iana.org/assignments/dns-parameters/WALLET/wallet-completed-template
   3361 static const rdata_info_t wallet_rdata_fields[] = {
   3362   FIELD("text")
   3363 };
   3364 
   3365 // https://www.iana.org/assignments/dns-parameters/CLA/cla-completed-template
   3366 static const rdata_info_t cla_rdata_fields[] = {
   3367   FIELD("text")
   3368 };
   3369 
   3370 // https://www.iana.org/assignments/dns-parameters/IPN/ipn-completed-template
   3371 // and https://datatracker.ietf.org/doc/draft-johnson-dns-ipn-cla/07/
   3372 static const rdata_info_t ipn_rdata_fields[] = {
   3373   FIELD("CBHE Node Number")
   3374 };
   3375 
   3376 static const rdata_info_t ta_rdata_fields[] = {
   3377   FIELD("key"),
   3378   FIELD("algorithm"),
   3379   FIELD("type"),
   3380   FIELD("digest")
   3381 };
   3382 
   3383 static const rdata_info_t dlv_rdata_fields[] = {
   3384   FIELD("key"),
   3385   FIELD("algorithm"),
   3386   FIELD("type"),
   3387   FIELD("digest")
   3388 };
   3389 
   3390 // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
   3391 static const type_info_t types[] = {
   3392   UNKNOWN_TYPE(0),
   3393 
   3394   TYPE("A", ZONE_TYPE_A, ZONE_CLASS_ANY, FIELDS(a_rdata_fields),
   3395             check_a_rr, parse_a_rdata),
   3396   TYPE("NS", ZONE_TYPE_NS, ZONE_CLASS_ANY, FIELDS(ns_rdata_fields),
   3397              check_ns_rr, parse_ns_rdata),
   3398   TYPE("MD", ZONE_TYPE_MD, ZONE_CLASS_ANY, FIELDS(md_rdata_fields), // obsolete
   3399              check_ns_rr, parse_ns_rdata),
   3400   TYPE("MF", ZONE_TYPE_MF, ZONE_CLASS_ANY, FIELDS(mf_rdata_fields), // obsolete
   3401              check_ns_rr, parse_ns_rdata),
   3402   TYPE("CNAME", ZONE_TYPE_CNAME, ZONE_CLASS_ANY, FIELDS(cname_rdata_fields),
   3403                 check_ns_rr, parse_ns_rdata),
   3404   TYPE("SOA", ZONE_TYPE_SOA, ZONE_CLASS_ANY, FIELDS(soa_rdata_fields),
   3405               check_soa_rr, parse_soa_rdata),
   3406   TYPE("MB", ZONE_TYPE_MB, ZONE_CLASS_ANY, FIELDS(mb_rdata_fields), // experimental
   3407              check_ns_rr, parse_ns_rdata),
   3408   TYPE("MG", ZONE_TYPE_MG, ZONE_CLASS_ANY, FIELDS(mg_rdata_fields), // experimental
   3409              check_ns_rr, parse_ns_rdata),
   3410   TYPE("MR", ZONE_TYPE_MR, ZONE_CLASS_ANY, FIELDS(mr_rdata_fields), // experimental
   3411              check_ns_rr, parse_ns_rdata),
   3412   TYPE("NULL", ZONE_TYPE_NULL, ZONE_CLASS_ANY, FIELDS(null_rdata_fields), // experimetal
   3413                check_generic_rr, parse_unknown_rdata),
   3414   TYPE("WKS", ZONE_TYPE_WKS, ZONE_CLASS_IN, FIELDS(wks_rdata_fields),
   3415               check_wks_rr, parse_wks_rdata),
   3416   TYPE("PTR", ZONE_TYPE_PTR, ZONE_CLASS_ANY, FIELDS(ptr_rdata_fields),
   3417               check_ns_rr, parse_ns_rdata),
   3418   TYPE("HINFO", ZONE_TYPE_HINFO, ZONE_CLASS_ANY, FIELDS(hinfo_rdata_fields),
   3419                 check_hinfo_rr, parse_hinfo_rdata),
   3420   TYPE("MINFO", ZONE_TYPE_MINFO, ZONE_CLASS_ANY, FIELDS(minfo_rdata_fields),
   3421                 check_minfo_rr, parse_minfo_rdata),
   3422   TYPE("MX", ZONE_TYPE_MX, ZONE_CLASS_ANY, FIELDS(mx_rdata_fields),
   3423              check_mx_rr, parse_mx_rdata),
   3424   TYPE("TXT", ZONE_TYPE_TXT, ZONE_CLASS_ANY, FIELDS(txt_rdata_fields),
   3425               check_txt_rr, parse_txt_rdata),
   3426   TYPE("RP", ZONE_TYPE_RP, ZONE_CLASS_ANY, FIELDS(rp_rdata_fields),
   3427              check_minfo_rr, parse_minfo_rdata),
   3428   TYPE("AFSDB", ZONE_TYPE_AFSDB, ZONE_CLASS_ANY, FIELDS(afsdb_rdata_fields),
   3429                 check_mx_rr, parse_mx_rdata),
   3430   TYPE("X25", ZONE_TYPE_X25, ZONE_CLASS_ANY, FIELDS(x25_rdata_fields),
   3431               check_x25_rr, parse_x25_rdata),
   3432   TYPE("ISDN", ZONE_TYPE_ISDN, ZONE_CLASS_ANY, FIELDS(isdn_rdata_fields),
   3433                check_isdn_rr, parse_isdn_rdata),
   3434   TYPE("RT", ZONE_TYPE_RT, ZONE_CLASS_ANY, FIELDS(rt_rdata_fields),
   3435              check_rt_rr, parse_rt_rdata),
   3436   TYPE("NSAP", ZONE_TYPE_NSAP, ZONE_CLASS_IN, FIELDS(nsap_rdata_fields),
   3437                check_nsap_rr, parse_nsap_rdata),
   3438   TYPE("NSAP-PTR", ZONE_TYPE_NSAP_PTR, ZONE_CLASS_IN, FIELDS(nsap_ptr_rdata_fields),
   3439                    check_nsap_ptr_rr, parse_nsap_ptr_rdata),
   3440   TYPE("SIG", ZONE_TYPE_SIG, ZONE_CLASS_ANY, FIELDS(sig_rdata_fields),
   3441               check_rrsig_rr, parse_rrsig_rdata),
   3442   TYPE("KEY", ZONE_TYPE_KEY, ZONE_CLASS_ANY, FIELDS(key_rdata_fields),
   3443               check_key_rr, parse_key_rdata),
   3444   TYPE("PX", ZONE_TYPE_PX, ZONE_CLASS_IN, FIELDS(px_rdata_fields),
   3445              check_px_rr, parse_px_rdata),
   3446   TYPE("GPOS", ZONE_TYPE_GPOS, ZONE_CLASS_ANY, FIELDS(gpos_rdata_fields),
   3447                check_gpos_rr, parse_gpos_rdata),
   3448   TYPE("AAAA", ZONE_TYPE_AAAA, ZONE_CLASS_IN, FIELDS(aaaa_rdata_fields),
   3449                check_aaaa_rr, parse_aaaa_rdata),
   3450   TYPE("LOC", ZONE_TYPE_LOC, ZONE_CLASS_ANY, FIELDS(loc_rdata_fields),
   3451               check_loc_rr, parse_loc_rdata),
   3452   TYPE("NXT", ZONE_TYPE_NXT, ZONE_CLASS_ANY, FIELDS(nxt_rdata_fields), // obsolete
   3453               check_nxt_rr, parse_nxt_rdata),
   3454   TYPE("EID", ZONE_TYPE_EID, ZONE_CLASS_IN, FIELDS(eid_rdata_fields),
   3455               check_eid_rr, parse_eid_rdata),
   3456   TYPE("NIMLOC", ZONE_TYPE_NIMLOC, ZONE_CLASS_IN, FIELDS(nimloc_rdata_fields),
   3457               check_eid_rr, parse_eid_rdata),
   3458   TYPE("SRV", ZONE_TYPE_SRV, ZONE_CLASS_IN, FIELDS(srv_rdata_fields),
   3459               check_srv_rr, parse_srv_rdata),
   3460   TYPE("ATMA", ZONE_TYPE_ATMA, ZONE_CLASS_IN, FIELDS(atma_rdata_fields),
   3461                check_atma_rr, parse_atma_rdata),
   3462   TYPE("NAPTR", ZONE_TYPE_NAPTR, ZONE_CLASS_IN, FIELDS(naptr_rdata_fields),
   3463                 check_naptr_rr, parse_naptr_rdata),
   3464   TYPE("KX", ZONE_TYPE_KX, ZONE_CLASS_IN, FIELDS(kx_rdata_fields),
   3465              check_mx_rr, parse_mx_rdata),
   3466   TYPE("CERT", ZONE_TYPE_CERT, ZONE_CLASS_ANY, FIELDS(cert_rdata_fields),
   3467                check_cert_rr, parse_cert_rdata),
   3468 
   3469   UNKNOWN_TYPE(38),
   3470 
   3471   TYPE("DNAME", ZONE_TYPE_DNAME, ZONE_CLASS_ANY, FIELDS(dname_rdata_fields),
   3472                 check_ns_rr, parse_ns_rdata),
   3473 
   3474   TYPE("SINK", ZONE_TYPE_SINK, ZONE_CLASS_ANY, FIELDS(sink_rdata_fields),
   3475                check_sink_rr, parse_sink_rdata),
   3476   UNKNOWN_TYPE(41),
   3477 
   3478   TYPE("APL", ZONE_TYPE_APL, ZONE_CLASS_IN, FIELDS(apl_rdata_fields),
   3479              check_apl_rr, parse_apl_rdata),
   3480   TYPE("DS", ZONE_TYPE_DS, ZONE_CLASS_ANY, FIELDS(ds_rdata_fields),
   3481              check_ds_rr, parse_ds_rdata),
   3482   TYPE("SSHFP", ZONE_TYPE_SSHFP, ZONE_CLASS_ANY, FIELDS(sshfp_rdata_fields),
   3483                 check_sshfp_rr, parse_sshfp_rdata),
   3484   TYPE("IPSECKEY", ZONE_TYPE_IPSECKEY, ZONE_CLASS_IN, FIELDS(ipseckey_rdata_fields),
   3485                    check_ipseckey_rr, parse_ipseckey_rdata),
   3486   TYPE("RRSIG", ZONE_TYPE_RRSIG, ZONE_CLASS_ANY, FIELDS(rrsig_rdata_fields),
   3487                 check_rrsig_rr, parse_rrsig_rdata),
   3488   TYPE("NSEC", ZONE_TYPE_NSEC, ZONE_CLASS_ANY, FIELDS(nsec_rdata_fields),
   3489                check_nsec_rr, parse_nsec_rdata),
   3490   TYPE("DNSKEY", ZONE_TYPE_DNSKEY, ZONE_CLASS_ANY, FIELDS(dnskey_rdata_fields),
   3491                  check_dnskey_rr, parse_dnskey_rdata),
   3492   TYPE("DHCID", ZONE_TYPE_DHCID, ZONE_CLASS_IN, FIELDS(dhcid_rdata_fields),
   3493                 check_dhcid_rr, parse_dhcid_rdata),
   3494   TYPE("NSEC3", ZONE_TYPE_NSEC3, ZONE_CLASS_ANY, FIELDS(nsec3_rdata_fields),
   3495                 check_nsec3_rr, parse_nsec3_rdata),
   3496   TYPE("NSEC3PARAM", ZONE_TYPE_NSEC3PARAM, ZONE_CLASS_ANY, FIELDS(nsec3param_rdata_fields),
   3497                      check_nsec3param_rr, parse_nsec3param_rdata),
   3498   TYPE("TLSA", ZONE_TYPE_TLSA, ZONE_CLASS_ANY, FIELDS(tlsa_rdata_fields),
   3499                check_tlsa_rr, parse_tlsa_rdata),
   3500   TYPE("SMIMEA", ZONE_TYPE_SMIMEA, ZONE_CLASS_ANY, FIELDS(smimea_rdata_fields),
   3501                  check_tlsa_rr, parse_tlsa_rdata),
   3502 
   3503   UNKNOWN_TYPE(54),
   3504 
   3505   TYPE("HIP", ZONE_TYPE_HIP, ZONE_CLASS_ANY, FIELDS(hip_rdata_fields),
   3506               check_hip_rr, parse_hip_rdata),
   3507   TYPE("NINFO", ZONE_TYPE_NINFO, ZONE_CLASS_ANY, FIELDS(ninfo_rdata_fields),
   3508               check_txt_rr, parse_txt_rdata),
   3509   TYPE("RKEY", ZONE_TYPE_RKEY, ZONE_CLASS_ANY, FIELDS(rkey_rdata_fields),
   3510                check_dnskey_rr, parse_dnskey_rdata),
   3511   TYPE("TALINK", ZONE_TYPE_TALINK, ZONE_CLASS_ANY, FIELDS(talink_rdata_fields),
   3512                  check_minfo_rr, parse_minfo_rdata),
   3513   TYPE("CDS", ZONE_TYPE_CDS, ZONE_CLASS_ANY, FIELDS(cds_rdata_fields),
   3514               check_ds_rr, parse_ds_rdata),
   3515   TYPE("CDNSKEY", ZONE_TYPE_CDNSKEY, ZONE_CLASS_ANY, FIELDS(cdnskey_rdata_fields),
   3516                   check_dnskey_rr, parse_dnskey_rdata),
   3517   TYPE("OPENPGPKEY", ZONE_TYPE_OPENPGPKEY, ZONE_CLASS_ANY, FIELDS(openpgpkey_rdata_fields),
   3518                      check_openpgpkey_rr, parse_openpgpkey_rdata),
   3519   TYPE("CSYNC", ZONE_TYPE_CSYNC, ZONE_CLASS_ANY, FIELDS(csync_rdata_fields),
   3520                 check_csync_rr, parse_csync_rdata),
   3521   TYPE("ZONEMD", ZONE_TYPE_ZONEMD, ZONE_CLASS_ANY, FIELDS(zonemd_rdata_fields),
   3522                  check_zonemd_rr, parse_zonemd_rdata),
   3523   TYPE("SVCB", ZONE_TYPE_SVCB, ZONE_CLASS_IN, FIELDS(svcb_rdata_fields),
   3524                check_svcb_rr, parse_svcb_rdata),
   3525   TYPE("HTTPS", ZONE_TYPE_HTTPS, ZONE_CLASS_IN, FIELDS(https_rdata_fields),
   3526                 check_https_rr, parse_https_rdata),
   3527   TYPE("DSYNC", ZONE_TYPE_DSYNC, ZONE_CLASS_ANY, FIELDS(dsync_rdata_fields),
   3528                 check_dsync_rr, parse_dsync_rdata),
   3529   UNKNOWN_TYPE(67),
   3530   UNKNOWN_TYPE(68),
   3531   UNKNOWN_TYPE(69),
   3532   UNKNOWN_TYPE(70),
   3533   UNKNOWN_TYPE(71),
   3534   UNKNOWN_TYPE(72),
   3535   UNKNOWN_TYPE(73),
   3536   UNKNOWN_TYPE(74),
   3537   UNKNOWN_TYPE(75),
   3538   UNKNOWN_TYPE(76),
   3539   UNKNOWN_TYPE(77),
   3540   UNKNOWN_TYPE(78),
   3541   UNKNOWN_TYPE(79),
   3542   UNKNOWN_TYPE(80),
   3543   UNKNOWN_TYPE(81),
   3544   UNKNOWN_TYPE(82),
   3545   UNKNOWN_TYPE(83),
   3546   UNKNOWN_TYPE(84),
   3547   UNKNOWN_TYPE(85),
   3548   UNKNOWN_TYPE(86),
   3549   UNKNOWN_TYPE(87),
   3550   UNKNOWN_TYPE(88),
   3551   UNKNOWN_TYPE(89),
   3552   UNKNOWN_TYPE(90),
   3553   UNKNOWN_TYPE(91),
   3554   UNKNOWN_TYPE(92),
   3555   UNKNOWN_TYPE(93),
   3556   UNKNOWN_TYPE(94),
   3557   UNKNOWN_TYPE(95),
   3558   UNKNOWN_TYPE(96),
   3559   UNKNOWN_TYPE(97),
   3560   UNKNOWN_TYPE(98),
   3561 
   3562   TYPE("SPF", ZONE_TYPE_SPF, ZONE_CLASS_ANY, FIELDS(spf_rdata_fields), // obsolete
   3563               check_txt_rr, parse_txt_rdata),
   3564 
   3565   UNKNOWN_TYPE(100),
   3566   UNKNOWN_TYPE(101),
   3567   UNKNOWN_TYPE(102),
   3568   UNKNOWN_TYPE(103),
   3569 
   3570   TYPE("NID", ZONE_TYPE_NID, ZONE_CLASS_ANY, FIELDS(nid_rdata_fields),
   3571               check_nid_rr, parse_nid_rdata),
   3572   TYPE("L32", ZONE_TYPE_L32, ZONE_CLASS_ANY, FIELDS(l32_rdata_fields),
   3573               check_l32_rr, parse_l32_rdata),
   3574   TYPE("L64", ZONE_TYPE_L64, ZONE_CLASS_ANY, FIELDS(l64_rdata_fields),
   3575               check_l64_rr, parse_l64_rdata),
   3576   TYPE("LP", ZONE_TYPE_LP, ZONE_CLASS_ANY, FIELDS(lp_rdata_fields),
   3577              check_mx_rr, parse_mx_rdata),
   3578   TYPE("EUI48", ZONE_TYPE_EUI48, ZONE_CLASS_ANY, FIELDS(eui48_rdata_fields),
   3579                 check_eui48_rr, parse_eui48_rdata),
   3580   TYPE("EUI64", ZONE_TYPE_EUI64, ZONE_CLASS_ANY, FIELDS(eui64_rdata_fields),
   3581                 check_eui64_rr, parse_eui64_rdata),
   3582 
   3583   UNKNOWN_TYPE(110),
   3584   UNKNOWN_TYPE(111),
   3585   UNKNOWN_TYPE(112),
   3586   UNKNOWN_TYPE(113),
   3587   UNKNOWN_TYPE(114),
   3588   UNKNOWN_TYPE(115),
   3589   UNKNOWN_TYPE(116),
   3590   UNKNOWN_TYPE(117),
   3591   UNKNOWN_TYPE(118),
   3592   UNKNOWN_TYPE(119),
   3593   UNKNOWN_TYPE(120),
   3594   UNKNOWN_TYPE(121),
   3595   UNKNOWN_TYPE(122),
   3596   UNKNOWN_TYPE(123),
   3597   UNKNOWN_TYPE(124),
   3598   UNKNOWN_TYPE(125),
   3599   UNKNOWN_TYPE(126),
   3600   UNKNOWN_TYPE(127),
   3601   UNKNOWN_TYPE(128),
   3602   UNKNOWN_TYPE(129),
   3603   UNKNOWN_TYPE(130),
   3604   UNKNOWN_TYPE(131),
   3605   UNKNOWN_TYPE(132),
   3606   UNKNOWN_TYPE(133),
   3607   UNKNOWN_TYPE(134),
   3608   UNKNOWN_TYPE(135),
   3609   UNKNOWN_TYPE(136),
   3610   UNKNOWN_TYPE(137),
   3611   UNKNOWN_TYPE(138),
   3612   UNKNOWN_TYPE(139),
   3613   UNKNOWN_TYPE(140),
   3614   UNKNOWN_TYPE(141),
   3615   UNKNOWN_TYPE(142),
   3616   UNKNOWN_TYPE(143),
   3617   UNKNOWN_TYPE(144),
   3618   UNKNOWN_TYPE(145),
   3619   UNKNOWN_TYPE(146),
   3620   UNKNOWN_TYPE(147),
   3621   UNKNOWN_TYPE(148),
   3622   UNKNOWN_TYPE(149),
   3623   UNKNOWN_TYPE(150),
   3624   UNKNOWN_TYPE(151),
   3625   UNKNOWN_TYPE(152),
   3626   UNKNOWN_TYPE(153),
   3627   UNKNOWN_TYPE(154),
   3628   UNKNOWN_TYPE(155),
   3629   UNKNOWN_TYPE(156),
   3630   UNKNOWN_TYPE(157),
   3631   UNKNOWN_TYPE(158),
   3632   UNKNOWN_TYPE(159),
   3633   UNKNOWN_TYPE(160),
   3634   UNKNOWN_TYPE(161),
   3635   UNKNOWN_TYPE(162),
   3636   UNKNOWN_TYPE(163),
   3637   UNKNOWN_TYPE(164),
   3638   UNKNOWN_TYPE(165),
   3639   UNKNOWN_TYPE(166),
   3640   UNKNOWN_TYPE(167),
   3641   UNKNOWN_TYPE(168),
   3642   UNKNOWN_TYPE(169),
   3643   UNKNOWN_TYPE(170),
   3644   UNKNOWN_TYPE(171),
   3645   UNKNOWN_TYPE(172),
   3646   UNKNOWN_TYPE(173),
   3647   UNKNOWN_TYPE(174),
   3648   UNKNOWN_TYPE(175),
   3649   UNKNOWN_TYPE(176),
   3650   UNKNOWN_TYPE(177),
   3651   UNKNOWN_TYPE(178),
   3652   UNKNOWN_TYPE(179),
   3653   UNKNOWN_TYPE(180),
   3654   UNKNOWN_TYPE(181),
   3655   UNKNOWN_TYPE(182),
   3656   UNKNOWN_TYPE(183),
   3657   UNKNOWN_TYPE(184),
   3658   UNKNOWN_TYPE(185),
   3659   UNKNOWN_TYPE(186),
   3660   UNKNOWN_TYPE(187),
   3661   UNKNOWN_TYPE(188),
   3662   UNKNOWN_TYPE(189),
   3663   UNKNOWN_TYPE(190),
   3664   UNKNOWN_TYPE(191),
   3665   UNKNOWN_TYPE(192),
   3666   UNKNOWN_TYPE(193),
   3667   UNKNOWN_TYPE(194),
   3668   UNKNOWN_TYPE(195),
   3669   UNKNOWN_TYPE(196),
   3670   UNKNOWN_TYPE(197),
   3671   UNKNOWN_TYPE(198),
   3672   UNKNOWN_TYPE(199),
   3673   UNKNOWN_TYPE(200),
   3674   UNKNOWN_TYPE(201),
   3675   UNKNOWN_TYPE(202),
   3676   UNKNOWN_TYPE(203),
   3677   UNKNOWN_TYPE(204),
   3678   UNKNOWN_TYPE(205),
   3679   UNKNOWN_TYPE(206),
   3680   UNKNOWN_TYPE(207),
   3681   UNKNOWN_TYPE(208),
   3682   UNKNOWN_TYPE(209),
   3683   UNKNOWN_TYPE(210),
   3684   UNKNOWN_TYPE(211),
   3685   UNKNOWN_TYPE(212),
   3686   UNKNOWN_TYPE(213),
   3687   UNKNOWN_TYPE(214),
   3688   UNKNOWN_TYPE(215),
   3689   UNKNOWN_TYPE(216),
   3690   UNKNOWN_TYPE(217),
   3691   UNKNOWN_TYPE(218),
   3692   UNKNOWN_TYPE(219),
   3693   UNKNOWN_TYPE(220),
   3694   UNKNOWN_TYPE(221),
   3695   UNKNOWN_TYPE(222),
   3696   UNKNOWN_TYPE(223),
   3697   UNKNOWN_TYPE(224),
   3698   UNKNOWN_TYPE(225),
   3699   UNKNOWN_TYPE(226),
   3700   UNKNOWN_TYPE(227),
   3701   UNKNOWN_TYPE(228),
   3702   UNKNOWN_TYPE(229),
   3703   UNKNOWN_TYPE(230),
   3704   UNKNOWN_TYPE(231),
   3705   UNKNOWN_TYPE(232),
   3706   UNKNOWN_TYPE(233),
   3707   UNKNOWN_TYPE(234),
   3708   UNKNOWN_TYPE(235),
   3709   UNKNOWN_TYPE(236),
   3710   UNKNOWN_TYPE(237),
   3711   UNKNOWN_TYPE(238),
   3712   UNKNOWN_TYPE(239),
   3713   UNKNOWN_TYPE(240),
   3714   UNKNOWN_TYPE(241),
   3715   UNKNOWN_TYPE(242),
   3716   UNKNOWN_TYPE(243),
   3717   UNKNOWN_TYPE(244),
   3718   UNKNOWN_TYPE(245),
   3719   UNKNOWN_TYPE(246),
   3720   UNKNOWN_TYPE(247),
   3721   UNKNOWN_TYPE(248),
   3722   UNKNOWN_TYPE(249),
   3723   UNKNOWN_TYPE(250),
   3724   UNKNOWN_TYPE(251),
   3725   UNKNOWN_TYPE(252),
   3726   UNKNOWN_TYPE(253),
   3727   UNKNOWN_TYPE(254),
   3728   UNKNOWN_TYPE(255),
   3729 
   3730   TYPE("URI", ZONE_TYPE_URI, ZONE_CLASS_ANY, FIELDS(uri_rdata_fields),
   3731               check_uri_rr, parse_uri_rdata),
   3732   TYPE("CAA", ZONE_TYPE_CAA, ZONE_CLASS_ANY, FIELDS(caa_rdata_fields),
   3733               check_caa_rr, parse_caa_rdata),
   3734   TYPE("AVC", ZONE_TYPE_AVC, ZONE_CLASS_ANY, FIELDS(avc_rdata_fields),
   3735               check_txt_rr, parse_txt_rdata),
   3736   TYPE("DOA", ZONE_TYPE_DOA, ZONE_CLASS_ANY, FIELDS(doa_rdata_fields),
   3737               check_doa_rr, parse_doa_rdata),
   3738   TYPE("AMTRELAY", ZONE_TYPE_AMTRELAY, ZONE_CLASS_ANY, FIELDS(amtrelay_rdata_fields),
   3739               check_amtrelay_rr, parse_amtrelay_rdata),
   3740   TYPE("RESINFO", ZONE_TYPE_RESINFO, ZONE_CLASS_ANY, FIELDS(resinfo_rdata_fields),
   3741               check_txt_rr, parse_txt_rdata),
   3742   TYPE("WALLET", ZONE_TYPE_WALLET, ZONE_CLASS_ANY, FIELDS(wallet_rdata_fields),
   3743               check_txt_rr, parse_txt_rdata),
   3744   TYPE("CLA", ZONE_TYPE_CLA, ZONE_CLASS_ANY, FIELDS(cla_rdata_fields),
   3745               check_txt_rr, parse_txt_rdata),
   3746   TYPE("IPN", ZONE_TYPE_IPN, ZONE_CLASS_ANY, FIELDS(ipn_rdata_fields),
   3747               check_ipn_rr, parse_ipn_rdata),
   3748 
   3749   UNKNOWN_TYPE(265),
   3750   UNKNOWN_TYPE(266),
   3751   UNKNOWN_TYPE(267),
   3752   UNKNOWN_TYPE(268),
   3753   UNKNOWN_TYPE(269),
   3754 
   3755   /* Map 32768 in hash.c to 270 */
   3756   TYPE("TA", ZONE_TYPE_TA, ZONE_CLASS_ANY, FIELDS(ta_rdata_fields), // obsolete
   3757               check_ds_rr, parse_ds_rdata),
   3758   /* Map 32769 in hash.c to 271 */
   3759   TYPE("DLV", ZONE_TYPE_DLV, ZONE_CLASS_ANY, FIELDS(dlv_rdata_fields), // obsolete
   3760               check_ds_rr, parse_ds_rdata)
   3761 };
   3762 
   3763 #undef UNKNOWN_CLASS
   3764 #undef CLASS
   3765 #undef UNKNOWN_TYPE
   3766 #undef TYPE
   3767 
   3768 diagnostic_pop()
   3769 
   3770 #endif // TYPES_H
   3771