Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/fallback/ip4.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,41 @@
#ifndef IP4_H
#define IP4_H

zone_nonnull_all
static zone_really_inline int32_t scan_ip4(
const char *text, uint8_t *wire, size_t *length)
{
const char *start = text;
uint32_t round = 0;
for (;;) {
uint8_t digits[3];
uint32_t octet;
digits[0] = (uint8_t)text[0] - '0';
digits[1] = (uint8_t)text[1] - '0';
digits[2] = (uint8_t)text[2] - '0';
if (digits[0] > 9)
return -1;
else if (digits[1] > 9)
(void)(text += 1), octet = digits[0];
else if (digits[2] > 9)
(void)(text += 2), octet = digits[0] * 10 + digits[1];
else
(void)(text += 3), octet = digits[0] * 100 + digits[1] * 10 + digits[2];

if (octet > 255)
return -1;
wire[round++] = (uint8_t)octet;
if (text[0] != '.' || round == 4)
break;
text += 1;
}

if (round != 4)
return -1;
*length = (uintptr_t)text - (uintptr_t)start;
return 4;
}

zone_nonnull_all
static zone_really_inline int32_t parse_ip4(
zone_parser_t *parser,
Expand Down
1 change: 1 addition & 0 deletions src/fallback/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "generic/wks.h"
#include "generic/loc.h"
#include "generic/gpos.h"
#include "generic/apl.h"
#include "types.h"
#include "fallback/type.h"
#include "parser.h"
Expand Down
74 changes: 74 additions & 0 deletions src/generic/apl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* apl.h -- Address Prefix Lists (RFC3123) parser
*
* Copyright (c) 2023, NLnet Labs. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef APL_H
#define APL_H

static zone_really_inline int32_t scan_apl(
const char *text, size_t length, uint8_t *octets, size_t size)
{
uint8_t negate = text[0] == '!';
uint8_t digits[3];
size_t count;
uint32_t prefix;
const uint8_t af_inet[2] = { 0x01, 0x00 }, af_inet6[2] = { 0x02, 0x00 };

// address family is immediately followed by a colon ":"
if (text[negate + 1] != ':')
return -1;

switch (text[negate]) {
case '1':
if (size < 8)
return -1;
memcpy(octets, af_inet, sizeof(af_inet));
if (scan_ip4(&text[negate+2], &octets[4], &count) == -1)
return -1;
count += negate + 2;
digits[0] = (uint8_t)text[count+1] - '0';
digits[1] = (uint8_t)text[count+2] - '0';
if (text[count] != '/' || digits[0] > 9)
return -1;
if (digits[1] > 9)
(void)(count += 2), prefix = digits[0];
else
(void)(count += 3), prefix = digits[0] * 10 + digits[1];
if (prefix > 32 || (size_t)count != length)
return -1;
octets[2] = (uint8_t)prefix;
octets[3] = (uint8_t)((negate << 7) | 4);
return 8;
case '2':
if (size < 20)
return -1;
memcpy(octets, af_inet6, sizeof(af_inet6));
if (scan_ip6(text, &octets[4], &count) == -1)
return -1;
count += negate + 2;
digits[0] = (uint8_t)text[count+1] - '0';
digits[1] = (uint8_t)text[count+2] - '0';
digits[2] = (uint8_t)text[count+3] - '0';
if (text[count] != '/' || digits[0] > 9)
return -1;
if (digits[1] > 9)
(void)(count += 2), prefix = digits[0];
else if (digits[2] > 9)
(void)(count += 3), prefix = digits[0] * 10 + digits[1];
else
(void)(count += 4), prefix = digits[0] * 100 + digits[1] * 10 + digits[0];
if (prefix > 128 || (size_t)count != length)
return -1;
octets[2] = (uint8_t)prefix;
octets[3] = (uint8_t)((negate << 7) | 16);
return 20;
default:
return -1;
}
}

#endif // APL_H
41 changes: 28 additions & 13 deletions src/generic/ip6.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ inet_pton4(const char *src, uint8_t *dst)
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
uint8_t tmp[NS_INADDRSZ], *tp;
const char *start = src;

saw_digit = 0;
octets = 0;
Expand All @@ -48,11 +49,11 @@ inet_pton4(const char *src, uint8_t *dst)
uint32_t new = *tp * 10 + (uint32_t)(pch - digits);

if (new > 255)
return (0);
return -1;
*tp = (uint8_t)new;
if (! saw_digit) {
if (++octets > 4)
return (0);
return -1;
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
Expand All @@ -61,13 +62,13 @@ inet_pton4(const char *src, uint8_t *dst)
*++tp = 0;
saw_digit = 0;
} else
return (0);
break;
}
if (octets < 4)
return (0);
return -1;

memcpy(dst, tmp, NS_INADDRSZ);
return (1);
return (int)(src - start);
}

/* int
Expand All @@ -92,14 +93,16 @@ inet_pton6(const char *src, uint8_t *dst)
const char *xdigits, *curtok;
int ch, saw_xdigit;
uint32_t val;
int len;
const char *start = src;

memset((tp = tmp), '\0', NS_IN6ADDRSZ);
endp = tp + NS_IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
return -1;
curtok = src;
saw_xdigit = 0;
val = 0;
Expand All @@ -112,7 +115,7 @@ inet_pton6(const char *src, uint8_t *dst)
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
return -1;
saw_xdigit = 1;
continue;
}
Expand All @@ -133,16 +136,17 @@ inet_pton6(const char *src, uint8_t *dst)
continue;
}
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0) {
(len = inet_pton4(curtok, tp)) > 0) {
src += len;
tp += NS_INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
return -1;
}
if (saw_xdigit) {
if (tp + NS_INT16SZ > endp)
return (0);
return -1;
*tp++ = (uint8_t) (val >> 8) & 0xff;
*tp++ = (uint8_t) val & 0xff;
}
Expand All @@ -161,9 +165,20 @@ inet_pton6(const char *src, uint8_t *dst)
tp = endp;
}
if (tp != endp)
return (0);
return -1;
memcpy(dst, tmp, NS_IN6ADDRSZ);
return (1);
return (int)(src - start);
}

zone_nonnull_all
static zone_really_inline int32_t scan_ip6(
const char *text, uint8_t *wire, size_t *length)
{
int len = inet_pton6(text, wire);
if (len == -1)
return -1;
*length = (size_t)len;
return 16;
}

zone_nonnull_all
Expand All @@ -178,7 +193,7 @@ static zone_really_inline int32_t parse_ip6(
if ((r = have_contiguous(parser, type, field, token)) < 0)
return r;

if (inet_pton6(token->data, &parser->rdata->octets[parser->rdata->length]) == 1) {
if (inet_pton6(token->data, &parser->rdata->octets[parser->rdata->length]) != -1) {
parser->rdata->length += 16;
return ZONE_IP6;
}
Expand Down
1 change: 1 addition & 0 deletions src/haswell/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "generic/wks.h"
#include "generic/loc.h"
#include "generic/gpos.h"
#include "generic/apl.h"
#include "types.h"
#include "westmere/type.h"
#include "parser.h"
Expand Down
42 changes: 41 additions & 1 deletion src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,41 @@ static int32_t parse_cert_rdata(
return accept_rr(parser, type);
}

zone_nonnull_all
static int32_t check_apl_rr(
zone_parser_t *parser, const zone_type_info_t *type)
{
// FIXME: check correctness of fields and total length
return accept_rr(parser, type);
}

zone_nonnull_all
static int32_t parse_apl_rdata(
zone_parser_t *parser, const zone_type_info_t *type, token_t *token)
{
int32_t code;
uint8_t *octets = parser->rdata->octets;
size_t size = ZONE_RDATA_SIZE;

// RDATA section for APL consists of zero or more items
while (token->code == CONTIGUOUS) {
int32_t length;
if ((length = scan_apl(token->data, token->length, octets, size)) < 0)
SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&type->rdata.fields[0]), TNAME(type));
assert(length == 8 /* ipv4 */ || length == 20 /* ipv6 */);
size -= (size_t)length;
octets += (size_t)length;
lex(parser, token);
}

parser->rdata->length = ZONE_RDATA_SIZE - size;

if ((code = have_delimiter(parser, type, token)) < 0)
return code;

return accept_rr(parser, type);
}

zone_nonnull_all
static int32_t check_ds_rr(
zone_parser_t *parser, const zone_type_info_t *type)
Expand Down Expand Up @@ -2285,6 +2320,10 @@ static const zone_field_info_t dname_rdata_fields[] = {
FIELD("source", ZONE_NAME, 0)
};

static const zone_field_info_t apl_rdata_fields[] = {
FIELD("prefix", ZONE_INT16, 0)
};

static const zone_symbol_t ds_digest_type_symbols[] = {
SYMBOL("GOST", 3),
SYMBOL("SHA-1", 1),
Expand Down Expand Up @@ -2551,8 +2590,9 @@ static const type_descriptor_t types[] = {

UNKNOWN_TYPE(40),
UNKNOWN_TYPE(41),
UNKNOWN_TYPE(42),

TYPE("APL", ZONE_APL, ZONE_IN, FIELDS(apl_rdata_fields),
check_apl_rr, parse_apl_rdata),
TYPE("DS", ZONE_DS, ZONE_ANY, FIELDS(ds_rdata_fields),
check_ds_rr, parse_ds_rdata),
TYPE("SSHFP", ZONE_SSHFP, ZONE_ANY, FIELDS(sshfp_rdata_fields),
Expand Down
11 changes: 11 additions & 0 deletions src/westmere/ip4.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ static inline int sse_inet_aton(const char* ipv4_string, uint8_t* destination, s
return (int)(length + check_mask - pattern_ptr[6]);
}

zone_nonnull_all
static zone_really_inline int32_t scan_ip4(
const char *text, uint8_t *wire, size_t *length)
{
size_t len;
if (sse_inet_aton(text, wire, &len) != 1)
return -1;
*length = len;
return 4;
}

zone_nonnull_all
static zone_really_inline int32_t parse_ip4(
zone_parser_t *parser,
Expand Down
1 change: 1 addition & 0 deletions src/westmere/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "generic/wks.h"
#include "generic/loc.h"
#include "generic/gpos.h"
#include "generic/apl.h"
#include "types.h"
#include "westmere/type.h"
#include "parser.h"
Expand Down
9 changes: 9 additions & 0 deletions tests/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,14 @@ static const char dname_generic_text[] =
PAD(" DNAME \\# 18 04686f7374076578616d706c6503636f6d00");
static const rdata_t dname_rdata = RDATA(HOST_EXAMPLE_COM);

static const char apl_text[] =
PAD("foo.example. IN APL 1:192.168.32.0/21 !1:192.168.38.0/28");
static const rdata_t apl_rdata =
RDATA(/* 1:192.168.32.0/21 */
1, 0, 21, 0x04, 192, 168, 32, 0,
/* !1:192.168.38.0/28 */
1, 0, 28, 0x84, 192, 168, 38, 0);

static const char sshfp_text[] =
PAD(" SSHFP 4 2 123456789abcdef67890123456789abcdef67890123456789abcdef123456789");
static const char sshfp_generic_text[] =
Expand Down Expand Up @@ -816,6 +824,7 @@ static const test_t tests[] = {
{ ZONE_CERT, cert_text, &cert_rdata },
{ ZONE_DNAME, dname_text, &dname_rdata },
{ ZONE_DNAME, dname_generic_text, &dname_rdata },
{ ZONE_APL, apl_text, &apl_rdata },
{ ZONE_SSHFP, sshfp_text, &sshfp_rdata },
{ ZONE_SSHFP, sshfp_generic_text, &sshfp_rdata },
{ ZONE_IPSECKEY, ipseckey_text, &ipseckey_rdata },
Expand Down