diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b00131..9245140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Correct lengths for GOST R 34.10-2012 and SM3 delegation signer (DS) digest algorithms +- Require the AMTRELAY relay field to be `.` for the no gateway relay type as + specified by RFC 8777 (#257) ## [0.2.3] - 2025-09-03 diff --git a/src/generic/types.h b/src/generic/types.h index 59f2d19..9da586e 100644 --- a/src/generic/types.h +++ b/src/generic/types.h @@ -2752,29 +2752,33 @@ static int32_t parse_amtrelay_rdata( if ((code = parse_int8(parser, type, &fields[2], rdata, token)) < 0) return code; - if (octets[1]) { - if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) - return code; - switch (octets[1]) { - case 1: /* IPv4 address */ - type = (const type_info_t *)amtrelay_ipv4; - fields = type->rdata.fields; - if ((code = parse_ip4(parser, type, &fields[3], rdata, token)) < 0) - return code; - break; - case 2: /* IPv6 address */ - type = (const type_info_t *)amtrelay_ipv6; - fields = type->rdata.fields; - if ((code = parse_ip6(parser, type, &fields[3], rdata, token)) < 0) - return code; - break; - case 3: /* domain name */ - if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0) - return code; - break; - default: - SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type)); - } + if ((code = take_contiguous(parser, type, &fields[3], token)) < 0) + return code; + switch (octets[1]) { + case 0: + /* no gateway requires a '.' as the relay in presentation format + * without parsing it into wireformat rdata */ + if (!(token->length == 1 && *token->data == '.')) + 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)); + break; + case 1: /* IPv4 address */ + type = (const type_info_t *)amtrelay_ipv4; + fields = type->rdata.fields; + if ((code = parse_ip4(parser, type, &fields[3], rdata, token)) < 0) + return code; + break; + case 2: /* IPv6 address */ + type = (const type_info_t *)amtrelay_ipv6; + fields = type->rdata.fields; + if ((code = parse_ip6(parser, type, &fields[3], rdata, token)) < 0) + return code; + break; + case 3: /* domain name */ + if ((code = parse_name(parser, type, &fields[3], rdata, token)) < 0) + return code; + break; + default: + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[3]), NAME(type)); } octets[1] |= D; if ((code = take_delimiter(parser, type, token)) < 0) diff --git a/tests/types.c b/tests/types.c index 3a1f2b0..a24b81a 100644 --- a/tests/types.c +++ b/tests/types.c @@ -995,7 +995,7 @@ static const rdata_t doa2_rdata = ); static const char amtrelay_text[] = - PAD("foo. AMTRELAY 200 0 0"); + PAD("foo. AMTRELAY 200 0 0 ."); static const char amtrelay_generic_text[] = PAD("foo. AMTRELAY \\# 2 c8 00"); static const rdata_t amtrelay_rdata =