Skip to content

Commit

Permalink
ATMA RR type
Browse files Browse the repository at this point in the history
  • Loading branch information
wtoorop committed Jan 20, 2025
1 parent 833e624 commit 92b6a47
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 69 deletions.
2 changes: 2 additions & 0 deletions include/zone.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ extern "C" {
#define ZONE_TYPE_NIMLOC (32u)
/** Server Selection @rfc{2782} */
#define ZONE_TYPE_SRV (33u)
/** ATM Address */
#define ZONE_TYPE_ATMA (34u)
/** Naming Authority Pointer @rfc{2915} @rfc{2168} @rfc{3403} */
#define ZONE_TYPE_NAPTR (35u)
/** Key Exchanger @rfc{2230} */
Expand Down
1 change: 1 addition & 0 deletions scripts/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ static const tuple_t types_and_classes[] = {
{ "EID", 31, true },
{ "NIMLOC", 32, true },
{ "SRV", 33, true },
{ "ATMA", 34, true },
{ "NAPTR", 35, true },
{ "KX", 36, true },
{ "CERT", 37, true },
Expand Down
1 change: 1 addition & 0 deletions src/fallback/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "generic/apl.h"
#include "generic/svcb.h"
#include "generic/cert.h"
#include "generic/atma.h"
#include "generic/algorithm.h"
#include "generic/types.h"
#include "generic/type.h"
Expand Down
215 changes: 215 additions & 0 deletions src/generic/atma.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
/*
* atma.h -- ATMA parser (see: https://web.archive.org/web/20190112072924/http://www.broadband-forum.org/ftp/pub/approved-specs/af-dans-0152.000.pdf )
*
* Copyright (c) 2025, NLnet Labs. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef ATMA_H
#define ATMA_H

static const uint8_t bad_atma_chars[256] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x00 - 0x07
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x08 - 0x0f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x10 - 0x17
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x18 - 0x10f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x20 - 0x27
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, // 0x28 - 0x2f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 - 0x37
0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x38 - 0x3f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x40 - 0x47
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x48 - 0x4f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x50 - 0x57
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x58 - 0x5f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x60 - 0x67
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x68 - 0x6f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x70 - 0x77
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x78 - 0x7f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x80 - 0x87
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x88 - 0x8f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x90 - 0x97
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x98 - 0x9f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa0 - 0xa7
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xa8 - 0xaf
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb0 - 0xb7
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xb8 - 0xbf
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc0 - 0xc7
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xc8 - 0xcf
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd0 - 0xd7
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xd8 - 0xdf
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe0 - 0xe7
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xe0 - 0xe7
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xf8 - 0xff
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xf8 - 0xff
};

static const uint8_t atma_increment[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01 - 0x07
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 - 0x0f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 - 0x17
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 - 0x10f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 - 0x27
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 - 0x2f
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0x30 - 0x37
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 - 0x3f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 - 0x47
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 - 0x4f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 - 0x57
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 - 0x5f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 - 0x67
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 - 0x6f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 - 0x77
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 - 0x7f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x87
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 - 0x8f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x97
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 - 0x9f
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 - 0xa7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa8 - 0xaf
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 - 0xb7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb8 - 0xbf
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 - 0xc7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc8 - 0xcf
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 - 0xd7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd8 - 0xdf
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 - 0xe7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 - 0xe7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf8 - 0x00
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf8 - 0x00
};


nonnull_all
static really_inline int32_t parse_atma_e164(
parser_t *parser,
const type_info_t *type,
const rdata_info_t *field,
rdata_t *rdata,
const token_t *token)
{
uint32_t bad_chars = 0;
for (size_t count=1; count < token->length; count++) {
const uint8_t octet = (uint8_t)token->data[count];
*rdata->octets = octet;
rdata->octets += atma_increment[octet];
bad_chars |= bad_atma_chars[octet];
}
if (bad_chars)
SEMANTIC_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));

return 0;
}

nonnull((1,2,4,5))
static really_inline int atma_stream_decode(
struct base16_state *state,
const char *src,
size_t srclen,
uint8_t *out,
size_t *outlen)
{
int ret = 0;
const uint8_t *s = (const uint8_t *) src;
uint8_t *o = (uint8_t *) out;
uint32_t q;

// Use local temporaries to avoid cache thrashing:
size_t olen = 0;
size_t slen = srclen;
struct base16_state st;
st.eof = state->eof;
st.bytes = state->bytes;
st.carry = state->carry;

if (st.eof) {
*outlen = 0;
return ret;
}

// Duff's device again:
switch (st.bytes)
{
#if defined(__SUNPRO_C)
#pragma error_messages(off, E_STATEMENT_NOT_REACHED)
#endif
for (;;)
#if defined(__SUNPRO_C)
#pragma error_messages(default, E_STATEMENT_NOT_REACHED)
#endif
{
case 0:
base16_dec_loop_generic_32(&s, &slen, &o, &olen);
if (slen-- == 0) {
ret = 1;
break;
}
if ((q = base16_table_dec_32bit_d0[*s++]) == 256) {
st.eof = BASE16_EOF;
break;
} else if (q == 257) {
continue;
}
st.carry = (uint8_t)q;
st.bytes = 1;

// fallthrough

case 1:
if (slen-- == 0) {
ret = 1;
break;
}
if ((q = base16_table_dec_32bit_d1[*s++]) == 256) {
st.eof = BASE16_EOF;
break;
} else if (q == 257) {
continue;
}
*o++ = st.carry | (uint8_t)q;
st.carry = 0;
st.bytes = 0;
olen++;
}
}

state->eof = st.eof;
state->bytes = st.bytes;
state->carry = st.carry;
*outlen = olen;
return ret;
}

nonnull((1,3,4))
static really_inline int atma_decode(
const char *src, size_t srclen, uint8_t *out, size_t *outlen)
{
struct base16_state state = { .eof = 0, .bytes = 0, .carry = 0 };
return atma_stream_decode(&state, src, srclen, out, outlen) & !state.bytes;
}

nonnull_all
static really_inline int32_t parse_atma(
parser_t *parser,
const type_info_t *type,
const rdata_info_t *field,
rdata_t *rdata,
const token_t *token)
{
if (token->length && (char)*token->data == '+') {
*rdata->octets++ = 1;
if ((uintptr_t)rdata->limit - (uintptr_t)rdata->octets < token->length)
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
return parse_atma_e164(parser, type, field, rdata, token);
}
size_t length = token->length / 2;
if ((uintptr_t)rdata->limit - (uintptr_t)rdata->octets < length)
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
*rdata->octets++ = 0;
if (!atma_decode(token->data, token->length, rdata->octets, &length))
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type));
rdata->octets += length;
return 0;
}

#endif // ATMA_H
4 changes: 2 additions & 2 deletions src/generic/base16.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static const uint32_t base16_table_dec_32bit_d0[256] = {
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 257, 256,
0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 256, 256,
256, 256, 256, 256, 256, 160, 176, 192, 208, 224, 240, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
Expand All @@ -52,7 +52,7 @@ static const uint32_t base16_table_dec_32bit_d1[256] = {
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 257, 256,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 256, 256,
256, 256, 256, 256, 256, 10, 11, 12, 13, 14, 15, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
Expand Down
64 changes: 32 additions & 32 deletions src/generic/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,38 @@ static const struct {
const mnemonic_t *mnemonic;
int32_t code;
} types_and_classes[256] = {
V(0), V(0), V(0), V(0), V(0), V(0), V(0), T(23),
V(0), V(0), V(0), V(0), T(40), V(0), T(61), V(0),
V(0), T(107), V(0), T(46), V(0), T(31), T(17), V(0),
V(0), V(0), V(0), V(0), T(104), T(10), T(52), V(0),
V(0), T(28), T(105), V(0), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), V(0), V(0), T(50), V(0), T(257),
V(0), V(0), V(0), V(0), V(0), T(3), T(45), V(0),
V(0), T(62), T(263), V(0), V(0), V(0), T(66), T(65),
V(0), V(0), T(20), V(0), T(22), T(1), V(0), T(108),
V(0), T(51), V(0), T(12), V(0), V(0), V(0), V(0),
T(262), T(258), V(0), V(0), T(42), V(0), V(0), V(0),
V(0), T(55), T(23), T(11), V(0), V(0), T(27), V(0),
T(21), V(0), V(0), T(18), V(0), V(0), V(0), V(0),
V(0), T(33), C(1), V(0), V(0), V(0), T(266), V(0),
V(0), T(24), T(39), T(30), V(0), V(0), C(3), T(5),
T(16), V(0), T(106), T(64), V(0), V(0), T(35), V(0),
V(0), C(2), T(43), V(0), V(0), C(4), V(0), V(0),
V(0), T(59), T(2), T(109), V(0), V(0), V(0), T(44),
T(7), V(0), V(0), V(0), V(0), V(0), V(0), V(0),
V(0), T(29), V(0), V(0), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), V(0), T(36), T(15), V(0), T(32),
T(26), T(38), T(19), V(0), T(8), V(0), V(0), V(0),
V(0), T(60), T(259), V(0), V(0), V(0), V(0), T(9),
T(256), V(0), V(0), V(0), V(0), V(0), T(6), V(0),
V(0), T(99), V(0), T(265), T(53), V(0), V(0), T(49),
T(37), V(0), V(0), V(0), V(0), V(0), V(0), V(0),
V(0), T(48), V(0), V(0), V(0), T(57), T(58), V(0),
V(0), T(4), V(0), V(0), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0),
V(0), V(0), T(3), T(99), V(0), T(258), T(64), V(0),
V(0), V(0), V(0), V(0), V(0), V(0), T(48), V(0),
T(262), V(0), V(0), V(0), T(20), V(0), V(0), V(0),
V(0), V(0), T(55), V(0), V(0), T(1), V(0), V(0),
V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0),
V(0), T(44), V(0), T(21), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), T(63), T(257), T(51), C(1), T(37),
V(0), V(0), T(35), V(0), T(58), T(263), V(0), V(0),
V(0), T(33), T(32), C(3), V(0), T(39), V(0), T(266),
V(0), T(5), V(0), V(0), C(2), T(43), T(29), V(0),
V(0), C(4), V(0), V(0), V(0), T(2), V(0), V(0),
V(0), V(0), V(0), V(0), V(0), V(0), T(7), V(0),
T(46), V(0), V(0), T(45), V(0), V(0), V(0), V(0),
V(0), V(0), T(25), T(105), T(53), V(0), T(36), T(18),
T(15), T(22), V(0), T(26), V(0), T(106), V(0), V(0),
T(38), T(8), V(0), T(57), V(0), V(0), T(49), T(19),
V(0), V(0), T(9), V(0), V(0), V(0), T(256), V(0),
V(0), T(28), V(0), V(0), V(0), T(24), V(0), V(0),
T(65), T(265), V(0), V(0), V(0), V(0), V(0), T(108),
T(30), T(60), V(0), V(0), V(0), T(16), V(0), V(0),
V(0), V(0), V(0), V(0), T(31), V(0), V(0), T(4),
T(11), V(0), T(56), T(14), T(104), V(0), T(42), T(13),
V(0), T(261), V(0), V(0), T(259), V(0), V(0), V(0),
V(0), T(47), V(0), V(0), V(0), T(12), V(0), V(0),
V(0), T(6), V(0), T(109), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), T(27), V(0), V(0), V(0), T(52),
V(0), V(0), V(0), T(10), V(0), V(0), V(0), T(59),
V(0), V(0), V(0), V(0), V(0), T(107), V(0), V(0),
T(50), T(62), T(17), V(0), V(0), V(0), V(0), T(66)
V(0), V(0), T(63), V(0), V(0), V(0), V(0), V(0),
V(0), V(0), V(0), V(0), V(0), V(0), T(56), T(14),
V(0), V(0), V(0), T(13), V(0), T(40), V(0), V(0),
V(0), T(34), V(0), T(25), V(0), V(0), V(0), T(47),
T(61), V(0), V(0), V(0), V(0), V(0), V(0), T(261)
};

#undef V
Expand Down Expand Up @@ -110,7 +110,7 @@ static really_inline uint8_t hash(uint64_t prefix)
prefix = le64toh(prefix);
uint32_t value = (uint32_t)((prefix >> 32) ^ prefix);
// magic value is generated using hash.c, rerun when adding types
return (uint8_t)((value * 3528039152ull) >> 32);
return (uint8_t)((value * 3530565426ull) >> 32);
}

nonnull_all
Expand Down
35 changes: 32 additions & 3 deletions src/generic/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,32 @@ static int32_t parse_srv_rdata(
return accept_rr(parser, type, rdata);
}

nonnull_all
static int32_t check_atma_rr(
parser_t *parser, const type_info_t *type, const rdata_t *rdata)
{
assert(rdata->octets >= parser->rdata->octets);
if ((uintptr_t)rdata->octets - (uintptr_t)parser->rdata->octets > 2)
return accept_rr(parser, type, rdata);
SYNTAX_ERROR(parser, "Invalid %s", NAME(type));
}

nonnull_all
static int32_t parse_atma_rdata(
parser_t *parser, const type_info_t *type, rdata_t *rdata, token_t *token)
{
int32_t code;
const rdata_info_t *fields = type->rdata.fields;

if ((code = have_contiguous(parser, type, &fields[0], token)) < 0)
return code;
if ((code = parse_atma(parser, type, &fields[0], rdata, token)) < 0)
return code;
if ((code = take_delimiter(parser, type, token)) < 0)
return code;
return accept_rr(parser, type, rdata);
}

nonnull_all
static int32_t check_naptr_rr(
parser_t *parser, const type_info_t *type, const rdata_t *rdata)
Expand Down Expand Up @@ -2841,6 +2867,10 @@ static const rdata_info_t srv_rdata_fields[] = {
FIELD("target")
};

static const rdata_info_t atma_rdata_fields[] = {
FIELD("address")
};

static const rdata_info_t naptr_rdata_fields[] = {
FIELD("order"),
FIELD("preference"),
Expand Down Expand Up @@ -3206,9 +3236,8 @@ static const type_info_t types[] = {
check_eid_rr, parse_eid_rdata),
TYPE("SRV", ZONE_TYPE_SRV, ZONE_CLASS_IN, FIELDS(srv_rdata_fields),
check_srv_rr, parse_srv_rdata),

UNKNOWN_TYPE(34),

TYPE("ATMA", ZONE_TYPE_ATMA, ZONE_CLASS_IN, FIELDS(atma_rdata_fields),
check_atma_rr, parse_atma_rdata),
TYPE("NAPTR", ZONE_TYPE_NAPTR, ZONE_CLASS_IN, FIELDS(naptr_rdata_fields),
check_naptr_rr, parse_naptr_rdata),
TYPE("KX", ZONE_TYPE_KX, ZONE_CLASS_IN, FIELDS(kx_rdata_fields),
Expand Down
Loading

0 comments on commit 92b6a47

Please sign in to comment.