:bar.svcb.example.com:64:\000\001\000\000\001\000\003\002h2:120
:bar.svcb.example.com:64:\000\003\000\000\001\000\003\002h3\000\003\000\002\005\334:120
:bar.svcb.example.com:64:\000\004\000\000\001\000\003\002h3\000\003\000\002\005\335:120
+:bar.svcb.example.com:64:\000\005\000\000\002\000\000\000\003\000\002\037D\000\007\000\020/dns-query{?dns}\000\010\000\000\000\011\000\004\000\035\000\027:120
+:bar.svcb.example.com:64:\000\006\000\003\345\000\006quoted\003\346\000\003foo\003\347\000\003bar:120
:baz.svcb.example.com:64:\000\000\004foo1\004svcb\007example\003net\000:120
:dsdelegation.example.com:43:m\341\010\001\312\361\352\256\315\253\347afpx\217\220\042EK\365\375\237\332:120
:escapedtext.example.com:16:\005begin\022the\040\042middle\042\040p\134art\007the\040end:120
kvs.insert(SvcParam(key, std::move(alpns)));
break;
}
+ case SvcParam::ohttp:
case SvcParam::no_default_alpn: {
if (len != 0) {
- throw std::out_of_range("invalid length for no-default-alpn");
+ throw std::out_of_range("invalid length for " + SvcParam::keyToString(key));
}
kvs.insert(SvcParam(key));
break;
kvs.insert(SvcParam(key, port));
break;
}
- case SvcParam::ipv4hint: /* fall-through */
+ case SvcParam::ipv4hint:
case SvcParam::ipv6hint: {
size_t addrLen = (key == SvcParam::ipv4hint ? 4 : 16);
if (len % addrLen != 0) {
kvs.insert(SvcParam(key, blob));
break;
}
+ case SvcParam::tls_supported_groups: {
+ if (len % 2 != 0) {
+ throw std::out_of_range("invalid length for " + SvcParam::keyToString(key));
+ }
+ vector<uint16_t> groups;
+ groups.reserve(len / 2);
+ auto stop = d_pos + len;
+ while (d_pos < stop)
+ {
+ uint16_t group = 0;
+ xfr16BitInt(group);
+ groups.push_back(group);
+ }
+ auto param = SvcParam(key, std::move(groups));
+ kvs.insert(std::move(param));
+ break;
+ }
default: {
std::string blob;
blob.reserve(len);
xfr16BitInt(param.getECH().size()); // size
xfrBlobNoSpaces(param.getECH());
break;
+ case SvcParam::ohttp:
+ xfr16BitInt(0); // no size
+ break;
+ case SvcParam::tls_supported_groups:
+ xfr16BitInt(2 * param.getTLSSupportedGroups().size()); // size
+ for (const auto& group: param.getTLSSupportedGroups()) {
+ xfr16BitInt(group);
+ }
+ break;
default:
xfr16BitInt(param.getValue().size());
xfrBlob(param.getValue());
switch (key) {
case SvcParam::no_default_alpn:
+ case SvcParam::ohttp:
if (d_pos != d_end && d_string.at(d_pos) != ' ') {
throw RecordTextException(k + " key can not have values");
}
val.insert(SvcParam(key, value));
break;
}
+ case SvcParam::tls_supported_groups: {
+ string string_value;
+ xfrRFC1035CharString(string_value);
+ if (string_value.empty()) {
+ throw RecordTextException("Value is required for SVC Param " + k);
+ }
+
+ vector<string> parts;
+ stringtok(parts, string_value, ",");
+
+ vector<uint16_t> values;
+ values.reserve(parts.size());
+ for (const auto& part : parts) {
+ uint16_t int_part{0};
+ try {
+ pdns::checked_stoi_into(int_part, part);
+ } catch (const std::invalid_argument&) {
+ throw RecordTextException("Value in invalid format for SVC Param " + k);
+ }
+ values.emplace_back(int_part);
+ }
+
+ val.insert(SvcParam(key, std::move(values)));
+ break;
+ }
+ case SvcParam::dohpath: {
+ string value;
+ xfrRFC1035CharString(value);
+ if (value.empty()) {
+ throw RecordTextException("Value is required for SVC Param " + k);
+ }
+ val.insert(SvcParam(key, value));
+ break;
+ }
default: {
string value;
xfrRFC1035CharString(value);
d_string.append(1, ' ');
d_string.append(SvcParam::keyToString(param.getKey()));
- if (param.getKey() != SvcParam::no_default_alpn) {
+ if (param.getKey() != SvcParam::no_default_alpn && param.getKey() != SvcParam::ohttp) {
d_string.append(1, '=');
}
d_string = str + '"' + d_string + '"';
break;
}
+ case SvcParam::ohttp:
+ // no value
+ break;
+ case SvcParam::tls_supported_groups: {
+ auto str = d_string;
+ d_string.clear();
+ bool first = true;
+ for (auto const &group: param.getTLSSupportedGroups()) {
+ if (!first) {
+ str += ',';
+ }
+ str += std::to_string(group);
+ first = false;
+ }
+ d_string = str;
+ break;
+ }
+ case SvcParam::dohpath:
default:
auto str = d_string;
d_string.clear();
{"port", SvcParam::SvcParamKey::port},
{"ipv4hint", SvcParam::SvcParamKey::ipv4hint},
{"ech", SvcParam::SvcParamKey::ech},
- {"ipv6hint", SvcParam::SvcParamKey::ipv6hint}
+ {"ipv6hint", SvcParam::SvcParamKey::ipv6hint},
+ {"dohpath", SvcParam::SvcParamKey::dohpath},
+ {"ohttp", SvcParam::SvcParamKey::ohttp},
+ {"tls-supported-groups", SvcParam::SvcParamKey::tls_supported_groups},
};
SvcParam::SvcParamKey SvcParam::keyFromString(const std::string& k) {
SvcParam::SvcParam(const SvcParamKey &key) {
d_key = key;
- if (d_key != SvcParamKey::no_default_alpn) {
+ if (d_key != SvcParamKey::no_default_alpn && d_key != SvcParamKey::ohttp) {
throw std::invalid_argument("can not create non-empty SvcParam for key '" + keyToString(key) + "'");
}
}
SvcParam::SvcParam(const SvcParamKey &key, const std::string &value) {
d_key = key;
- if (d_key != SvcParamKey::ech && d_key < 7) {
+ if (d_key != SvcParamKey::ech && d_key != SvcParamKey::dohpath && d_key < 10) {
throw std::invalid_argument("can not create SvcParam for " + keyToString(key) + " with a string value");
}
if (d_key == SvcParamKey::ech) {
d_ipHints = std::move(value);
}
+SvcParam::SvcParam(const SvcParamKey &key, std::vector<uint16_t> &&value) : d_key(key) {
+ if (d_key != SvcParamKey::tls_supported_groups) {
+ throw std::invalid_argument("can not create SvcParam for " + keyToString(key) + " with a uint16 value-vector");
+ }
+ d_tls_supported_groups = std::move(value);
+}
+
SvcParam::SvcParam(const SvcParamKey &key, const uint16_t value) {
d_key = key;
if (d_key != SvcParamKey::port) {
}
const std::string& SvcParam::getValue() const {
- if (d_key < 7) {
+ if (d_key != SvcParamKey::dohpath && d_key < 10) {
throw std::invalid_argument("getValue called for non-single value key '" + keyToString(d_key) + "'");
}
return d_value;
}
+
+const std::vector<uint16_t>& SvcParam::getTLSSupportedGroups() const {
+ if (d_key != SvcParam::tls_supported_groups) {
+ throw std::invalid_argument("getTLSSupportedGroups called for non-tls-supported-groups key '" + keyToString(d_key) + "'");
+ }
+ return d_tls_supported_groups;
+}
class SvcParam {
public:
enum SvcParamKey: uint16_t {
- // TODO link to IANA registry
+ // https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml#dns-svcparamkeys
/* When adding new values, you *must* update SvcParam::SvcParam(const std::string &key, const std::string &value)
* in svc-record.cc with the new numbers
*/
port = 3,
ipv4hint = 4,
ech = 5,
- ipv6hint = 6
+ ipv6hint = 6,
+ dohpath = 7,
+ ohttp = 8,
+ tls_supported_groups = 9, /* https://datatracker.ietf.org/doc/draft-ietf-tls-key-share-prediction/ */
};
//! empty Param, unusable
//! To create a multi-value SvcParam with key values (like mandatory)
SvcParam(const SvcParamKey &key, std::set<SvcParamKey> &&value);
- //! To create and ipv{4,6}hists SvcParam
+ //! To create an ipv{4,6}hists SvcParam
SvcParam(const SvcParamKey &key, std::vector<ComboAddress> &&value);
+ //! To create a tls-supported-groups SvcParam
+ SvcParam(const SvcParamKey &key, std::vector<uint16_t> &&value);
+
//! To create a port SvcParam
SvcParam(const SvcParamKey &key, const uint16_t value);
const std::set<SvcParamKey>& getMandatory() const;
const std::string& getECH() const;
const std::string& getValue() const;
+ const std::vector<uint16_t>& getTLSSupportedGroups() const;
bool getAutoHint() const { return d_autohint; };
void setAutoHint(const bool value) { d_autohint = value; };
std::set<SvcParamKey> d_mandatory; // For mandatory
std::vector<ComboAddress> d_ipHints; // For ipv{6,4}hints
std::string d_ech; // For Encrypted Client Hello
+ std::vector<uint16_t> d_tls_supported_groups; // For tls-supported-groups
uint16_t d_port{0}; // For port
// Set to true if we encountered an "auto" field in hints
(CASE_L(QType::SVCB, R"XXX(16 foo.example.org. alpn=f\\\092oo\092,bar,h2)XXX", R"XXX(16 foo.example.org. alpn=f\\\\oo\\,bar,h2)XXX", "\x00\x10\3foo\7example\3org\x00\x00\x01\x00\x0c\x08\x66\\oo,bar\x02h2"))
// END SVCB draft test vectors
+ (CASE_S(QType::SVCB, "1 foo.powerdns.org. dohpath=\"path\"", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x07\0\x04path"))
+ (CASE_L(QType::SVCB, "1 foo.powerdns.org. dohpath=/q{?dns}", "1 foo.powerdns.org. dohpath=\"/q{?dns}\"", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x07\0\x08/q{?dns}"))
+ (CASE_S(QType::SVCB, "1 foo.powerdns.org. ohttp", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x08\x00\x00"))
+ (CASE_S(QType::SVCB, "1 foo.powerdns.org. tls-supported-groups=29,23", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x09\x00\x04\x00\x1d\x00\x17"))
+ (CASE_S(QType::SVCB, "1 foo.powerdns.org. port=8004 tls-supported-groups=29,23", "\0\x01\3foo\x08powerdns\x03org\x00\x00\x03\x00\x02\x1f\x44\0\x09\x00\x04\x00\x1d\x00\x17"))
+
(CASE_S(QType::HHIT, "1234abcd", "\xd7\x6d\xf8\x69\xb7\x1d"))
(CASE_L(QType::HHIT, "1234 abcd", "1234abcd", "\xd7\x6d\xf8\x69\xb7\x1d"))
(CASE_S(QType::BRID, "1234abcd", "\xd7\x6d\xf8\x69\xb7\x1d"))
32,1,13,184,0,0,0,0,0,0,0,0,0,0,0,2}));
}
+BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_dohpath) {
+ DNSName name("powerdns.com.");
+ vector<uint8_t> packet;
+ DNSPacketWriter pwR(packet, name, QType::SVCB, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+
+ set<SvcParam> params({SvcParam(SvcParam::dohpath, "a very bogus dohpath value")});
+
+ pwR.startRecord(name, QType::SVCB);
+ pwR.commit();
+ auto start = pwR.getContent().size();
+
+ pwR.xfrSvcParamKeyVals(params);
+ pwR.commit();
+ auto cit = pwR.getContent().begin();
+ for (size_t i = 0; i<start; i++) {
+ cit++;
+ }
+
+ vector content(cit, pwR.getContent().end());
+ BOOST_CHECK(content == vector<uint8_t>({0, 7, 0, 26,
+ 'a',' ','v','e','r','y',' ','b','o','g','u','s',' ',
+ 'd','o','h','p','a','t','h',' ','v','a','l','u','e'
+ }));
+}
+
+BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_ohttp) {
+ DNSName name("powerdns.com.");
+ vector<uint8_t> packet;
+ DNSPacketWriter pwR(packet, name, QType::SVCB, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+
+ set<SvcParam> params({SvcParam(SvcParam::ohttp)});
+
+ pwR.startRecord(name, QType::SVCB);
+ pwR.commit();
+ auto start = pwR.getContent().size();
+
+ pwR.xfrSvcParamKeyVals(params);
+ pwR.commit();
+ auto cit = pwR.getContent().begin();
+ for (size_t i = 0; i<start; i++) {
+ cit++;
+ }
+
+ vector content(cit, pwR.getContent().end());
+ BOOST_CHECK(content == vector<uint8_t>({0, 8, 0, 0}));
+}
+
+BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_tls_supported_groups) {
+ DNSName name("powerdns.com.");
+ vector<uint8_t> packet;
+ DNSPacketWriter pwR(packet, name, QType::SVCB, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+
+ vector<uint16_t> groups({29, 23});
+ set<SvcParam> params({SvcParam(SvcParam::tls_supported_groups, std::move(groups))});
+
+ pwR.startRecord(name, QType::SVCB);
+ pwR.commit();
+ auto start = pwR.getContent().size();
+
+ pwR.xfrSvcParamKeyVals(params);
+ pwR.commit();
+ auto cit = pwR.getContent().begin();
+ for (size_t i = 0; i<start; i++) {
+ cit++;
+ }
+
+ vector<uint8_t> content(cit, pwR.getContent().end());
+ BOOST_CHECK(content == vector<uint8_t>({
+ 0, 9, // key 9
+ 0, 4, // size
+ 0, 0x1d, // 29
+ 0, 0x17, // 23
+ }));
+}
+
BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_generic) {
DNSName name("powerdns.com.");
vector<uint8_t> packet;
pwR.xfrSvcParamKeyVals(params);
pwR.commit();
auto cit = pwR.getContent().begin();
- for (size_t i = 0; i<start; i++)
+ for (size_t i = 0; i<start; i++) {
cit++;
+ }
- vector<uint8_t> c(cit, pwR.getContent().end());
- BOOST_CHECK(c == vector<uint8_t>({2,154,0,11,
+ vector<uint8_t> content(cit, pwR.getContent().end());
+ BOOST_CHECK(content == vector<uint8_t>({2,154,0,11,
'm','y','c','o','o','l','v','a','l','u','e'
}));
}
pwR.xfrSvcParamKeyVals(params);
pwR.commit();
auto cit = pwR.getContent().begin();
- for (size_t i = 0; i<start; i++)
+ for (size_t i = 0; i<start; i++) {
cit++;
+ }
- vector<uint8_t> c(cit, pwR.getContent().end());
- BOOST_CHECK(c == vector<uint8_t>({
+ vector<uint8_t> content(cit, pwR.getContent().end());
+ BOOST_CHECK(content == vector<uint8_t>({
0,1,0,10,2,'h','2',3,'h','2','c',2,'h','3', // alpn
0,3,0,2,0,53, // port
0,6,0,32, // ipv6
writer.xfrNodeOrLocatorID(in);
writer.commit();
auto cit = writer.getContent().begin();
- for (size_t i = 0; i<start; i++)
+ for (size_t i = 0; i<start; i++) {
cit++;
+ }
- vector<uint8_t> c(cit, writer.getContent().end());
- BOOST_CHECK(c == vector<uint8_t>({
+ vector<uint8_t> content(cit, writer.getContent().end());
+ BOOST_CHECK(content == vector<uint8_t>({
0, 0, 0, 0,
0, 0, 0, 1}));
}
BOOST_CHECK_THROW(rtr7.xfrSvcParamKeyVals(v), RecordTextException);
}
+BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_dohpath) {
+ string source("dohpath=\"foo/bar\"");
+ set<SvcParam> vals;
+ RecordTextReader(source).xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 1U);
+ BOOST_CHECK_EQUAL(vals.begin()->getKey(), SvcParam::dohpath);
+ BOOST_CHECK_EQUAL(vals.begin()->getValue(), "foo/bar");
+
+ // Check the writer
+ string target;
+ RecordTextWriter rtw(target);
+ rtw.xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(target, source);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("dohpath=").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ // Generic
+ vals.clear();
+ RecordTextReader ("key7=\"foo/bar\"").xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 1U);
+ BOOST_CHECK_EQUAL(vals.begin()->getKey(), SvcParam::dohpath);
+ BOOST_CHECK_EQUAL(vals.begin()->getValue(), "foo/bar");
+
+ vals.clear();
+ RecordTextReader ("key7=foo/bar").xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 1U);
+ BOOST_CHECK_EQUAL(vals.begin()->getKey(), SvcParam::dohpath);
+ BOOST_CHECK_EQUAL(vals.begin()->getValue(), "foo/bar");
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key7").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key7=").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key7=\"\"").xfrSvcParamKeyVals(vals), RecordTextException);
+}
+
BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_mandatory) {
string source("mandatory=alpn");
RecordTextReader rtr(source);
BOOST_CHECK_THROW(rtr9.xfrSvcParamKeyVals(v), RecordTextException);
}
+BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_tls_supported_groups) {
+ string source("tls-supported-groups=29,23");
+ std::vector<uint16_t> expected_value{29, 23};
+ set<SvcParam> vals;
+ RecordTextReader (source).xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 1U);
+ BOOST_CHECK_EQUAL(vals.begin()->getKey(), SvcParam::tls_supported_groups);
+ BOOST_CHECK(vals.begin()->getTLSSupportedGroups() == expected_value);
+
+ // Check the writer
+ string target;
+ RecordTextWriter(target).xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(target, source);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("tls-supported-groups=").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("tls-supported-groups=foo,bar").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ // Generic
+ vals.clear();
+ RecordTextReader ("key9=29,23").xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 1U);
+ BOOST_CHECK_EQUAL(vals.begin()->getKey(), SvcParam::tls_supported_groups);
+ BOOST_CHECK(vals.begin()->getTLSSupportedGroups() == expected_value);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key9").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key9=").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key9=\"\"").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key9=foo,bar").xfrSvcParamKeyVals(vals), RecordTextException);
+}
+
+BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_ohttp) {
+ string source("ohttp");
+ set<SvcParam> vals;
+ RecordTextReader(source).xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 1U);
+ BOOST_CHECK(vals.begin()->getKey() == SvcParam::ohttp);
+
+ // Check the writer
+ string target;
+ RecordTextWriter(target).xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(target, source);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("ohttp=").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ // Generic
+ vals.clear();
+ RecordTextReader("key8").xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 1U);
+ BOOST_CHECK_EQUAL(vals.begin()->getKey(), SvcParam::ohttp);
+ BOOST_CHECK(vals.begin()->getKey() == SvcParam::SvcParamKey::ohttp);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key8=").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ RecordTextReader("key8 ipv4hint=1.2.3.4").xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 2U);
+ BOOST_CHECK_EQUAL(std::count_if(vals.begin(), vals.end(), [](const SvcParam& param) { return param.getKey() == SvcParam::ohttp; }), 1);
+
+ vals.clear();
+ RecordTextReader("ipv4hint=1.2.3.4 key8").xfrSvcParamKeyVals(vals);
+ BOOST_CHECK_EQUAL(vals.size(), 2U);
+ BOOST_CHECK_EQUAL(std::count_if(vals.begin(), vals.end(), [](const SvcParam& param) { return param.getKey() == SvcParam::ohttp; }), 1);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key8=port=123 ipv4hint=1.2.3.4").xfrSvcParamKeyVals(vals), RecordTextException);
+
+ vals.clear();
+ BOOST_CHECK_THROW(RecordTextReader("key8=port=123").xfrSvcParamKeyVals(vals), RecordTextException);
+}
+
BOOST_AUTO_TEST_CASE(test_xfrSvcParamKeyVals_port) {
string source("port=53");
RecordTextReader rtr(source);
BOOST_CHECK(k == 6);
BOOST_CHECK(k == SvcParam::ipv6hint);
+ k = SvcParam::keyFromString("dohpath");
+ BOOST_CHECK(k == 7);
+ BOOST_CHECK(k == SvcParam::dohpath);
+
+ k = SvcParam::keyFromString("ohttp");
+ BOOST_CHECK(k == 8);
+ BOOST_CHECK(k == SvcParam::ohttp);
+
+ k = SvcParam::keyFromString("tls-supported-groups");
+ BOOST_CHECK(k == 9);
+ BOOST_CHECK(k == SvcParam::tls_supported_groups);
+
k = SvcParam::keyFromString("key0");
BOOST_CHECK(k == 0);
BOOST_CHECK(k == SvcParam::mandatory);
BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::ipv4hint), "ipv4hint");
BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::ech), "ech");
BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::ipv6hint), "ipv6hint");
- BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::SvcParamKey(7)), "key7");
+ BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::dohpath), "dohpath");
+ BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::ohttp), "ohttp");
+ BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::tls_supported_groups), "tls-supported-groups");
+ BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::SvcParamKey(10)), "key10");
BOOST_CHECK_EQUAL(SvcParam::keyToString(SvcParam::SvcParamKey(666)), "key666");
}
BOOST_CHECK_THROW(SvcParam(SvcParam::port, val), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, val), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, val), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ohttp, val), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::tls_supported_groups, val), std::invalid_argument);
SvcParam param(SvcParam::keyFromString("no-default-alpn"));
BOOST_CHECK_NO_THROW(param = SvcParam(SvcParam::ech, base64val));
BOOST_CHECK_THROW(param.getIPHints(), std::invalid_argument);
BOOST_CHECK_THROW(param.getMandatory(), std::invalid_argument);
BOOST_CHECK_THROW(param.getPort(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getTLSSupportedGroups(), std::invalid_argument);
// TODO test bad base64 value
// BOOST_CHECK_THROW(SvcParam(SvcParam::ech, val), std::invalid_argument);
BOOST_CHECK_THROW(param.getIPHints(), std::invalid_argument);
BOOST_CHECK_THROW(param.getMandatory(), std::invalid_argument);
BOOST_CHECK_THROW(param.getPort(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getTLSSupportedGroups(), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(test_SvcParam_ctor_set_string_value) {
set<string> val({"foo", "bar", "baz"});
- BOOST_CHECK_THROW(SvcParam(SvcParam::alpn, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::no_default_alpn, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::port, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::ech, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, std::move(val)), std::invalid_argument);
-
- set<string> mandatoryVal = {"alpn", "key666"};
- set<SvcParam::SvcParamKey> mandatoryExpected = {SvcParam::alpn, (SvcParam::SvcParamKey)666};
+ BOOST_CHECK_THROW(SvcParam(SvcParam::alpn, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::no_default_alpn, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::port, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ech, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::dohpath, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ohttp, set<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::tls_supported_groups, set<string>(val)), std::invalid_argument);
+
+ set<string> mandatoryVal = {"alpn", "ohttp", "key666"};
+ set<SvcParam::SvcParamKey> mandatoryExpected = {SvcParam::alpn, SvcParam::ohttp, (SvcParam::SvcParamKey)666};
SvcParam param(SvcParam::keyFromString("no-default-alpn"));
BOOST_CHECK_NO_THROW(param = SvcParam(SvcParam::keyFromString("mandatory"), std::move(mandatoryVal)));
BOOST_CHECK_THROW(param.getIPHints(), std::invalid_argument);
BOOST_CHECK_THROW(param.getPort(), std::invalid_argument);
BOOST_CHECK_THROW(param.getValue(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getTLSSupportedGroups(), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(test_SvcParam_ctor_vector_string_value) {
auto val = vector<string>({"h3, h2"});
auto checkVal = val;
- BOOST_CHECK_THROW(SvcParam(SvcParam::mandatory, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::no_default_alpn, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::port, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::ech, std::move(val)), std::invalid_argument);
- BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, std::move(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::mandatory, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::no_default_alpn, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::port, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ech, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::dohpath, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ohttp, vector<string>(val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::tls_supported_groups, vector<string>(val)), std::invalid_argument);
SvcParam param(SvcParam::keyFromString("no-default-alpn"));
BOOST_CHECK_NO_THROW(param = SvcParam(SvcParam::keyFromString("alpn"), std::move(val)));
BOOST_CHECK_THROW(param.getIPHints(), std::invalid_argument);
BOOST_CHECK_THROW(param.getPort(), std::invalid_argument);
BOOST_CHECK_THROW(param.getValue(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getTLSSupportedGroups(), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(test_SvcParam_ctor_set_comboaddress_value) {
BOOST_CHECK_THROW(SvcParam(SvcParam::no_default_alpn, std::move(v4Val)), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::port, std::move(v4Val)), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::ech, std::move(v4Val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::dohpath, vector<ComboAddress>(v4Val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ohttp, vector<ComboAddress>(v4Val)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::tls_supported_groups, vector<ComboAddress>(v4Val)), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, std::move(v4Val)), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, std::move(v6Val)), std::invalid_argument);
BOOST_CHECK_THROW(param.getECH(), std::invalid_argument);
BOOST_CHECK_THROW(param.getPort(), std::invalid_argument);
BOOST_CHECK_THROW(param.getValue(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getTLSSupportedGroups(), std::invalid_argument);
BOOST_CHECK_NO_THROW(param = SvcParam(SvcParam::ipv6hint, std::move(v6Val)));
retval.clear();
BOOST_CHECK_THROW(param.getECH(), std::invalid_argument);
BOOST_CHECK_THROW(param.getPort(), std::invalid_argument);
BOOST_CHECK_THROW(param.getValue(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getTLSSupportedGroups(), std::invalid_argument);
}
BOOST_AUTO_TEST_CASE(test_SvcParam_ctor_uint16_value) {
BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, port), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::ech, port), std::invalid_argument);
BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, port), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::dohpath, port), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ohttp, port), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::tls_supported_groups, port), std::invalid_argument);
SvcParam param(SvcParam::keyFromString("no-default-alpn"));
BOOST_CHECK_NO_THROW(param = SvcParam(SvcParam::port, port));
BOOST_CHECK_THROW(param.getECH(), std::invalid_argument);
BOOST_CHECK_THROW(param.getIPHints(), std::invalid_argument);
BOOST_CHECK_THROW(param.getValue(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getTLSSupportedGroups(), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(test_SvcParam_ctor_vector_uint16_value) {
+ vector<uint16_t> groups({29, 23});
+ auto checkVal = groups;
+
+ BOOST_CHECK_THROW(SvcParam(SvcParam::mandatory, vector<uint16_t>(groups)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::alpn, vector<uint16_t>(groups)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::no_default_alpn, vector<uint16_t>(groups)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ipv4hint, vector<uint16_t>(groups)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ech, vector<uint16_t>(groups)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ipv6hint, vector<uint16_t>(groups)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::dohpath, vector<uint16_t>(groups)), std::invalid_argument);
+ BOOST_CHECK_THROW(SvcParam(SvcParam::ohttp, vector<uint16_t>(groups)), std::invalid_argument);
+
+ SvcParam param(SvcParam::keyFromString("no-default-alpn"));
+ BOOST_CHECK_NO_THROW(param = SvcParam(SvcParam::tls_supported_groups, vector<uint16_t>(groups)));
+ auto retval = param.getTLSSupportedGroups();
+ BOOST_CHECK_EQUAL_COLLECTIONS(checkVal.begin(), checkVal.end(), retval.begin(), retval.end());
+ BOOST_CHECK_THROW(param.getMandatory(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getALPN(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getECH(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getIPHints(), std::invalid_argument);
+ BOOST_CHECK_THROW(param.getValue(), std::invalid_argument);
}
BOOST_AUTO_TEST_SUITE_END()
-f3e86fd522b08d4812505da489ecb5b0 ../regression-tests/zones/example.com
+196ff1338193d25caf18c4ad61620ed7 ../regression-tests/zones/example.com
5cce94d1d050925d3bb8c5271a10961b ../regression-tests/zones/test.com
e5e3ee998d151fe194b98997eaa36c53 ../regression-tests/zones/test.dyndns
dee3e8b568549d9450134b555ca73990 ../regression-tests/zones/sub.test.dyndns
9aeed2c26d0c3ba3baf22dfa9568c451 ../regression-tests/zones/2.0.192.in-addr.arpa
99c73e8b5db5781fec1ac3fa6a2662a9 ../regression-tests/zones/cryptokeys.org
1f9e19be0cff67330f3a0a5347654f91 ../regression-tests/zones/hiddencryptokeys.org
-291489428c41bb9391e22bead5e94511 ../modules/tinydnsbackend/data
-cac5364329a0c45f7ac4c8eeeb0cf774 ../modules/tinydnsbackend/data.cdb
+c0c013171adc9e838fe0263150205406 ../modules/tinydnsbackend/data
+979d7e1b1f025ce8964dc29f76723232 ../modules/tinydnsbackend/data.cdb
0 bar.svcb.example.com. 120 IN SVCB 1 . alpn=h2
0 bar.svcb.example.com. 120 IN SVCB 3 . alpn=h3 port=1500
0 bar.svcb.example.com. 120 IN SVCB 4 . alpn=h3 port=1501
+0 bar.svcb.example.com. 120 IN SVCB 5 . no-default-alpn port=8004 dohpath="/dns-query{?dns}" ohttp tls-supported-groups=29,23
+0 bar.svcb.example.com. 120 IN SVCB 6 . key997="quoted" key998="foo" key999="bar"
2 . 32768 IN OPT
2 bar.svcb.example.com. 120 IN A 192.0.2.1
2 bar.svcb.example.com. 120 IN AAAA 2001:db8::3:1
0 bar.svcb.example.com. 120 IN SVCB 1 . alpn=h2
0 bar.svcb.example.com. 120 IN SVCB 3 . alpn=h3 port=1500
0 bar.svcb.example.com. 120 IN SVCB 4 . alpn=h3 port=1501
+0 bar.svcb.example.com. 120 IN SVCB 5 . no-default-alpn port=8004 dohpath="/dns-query{?dns}" ohttp tls-supported-groups=29,23
+0 bar.svcb.example.com. 120 IN SVCB 6 . key997="quoted" key998="foo" key999="bar"
2 . 32768 IN OPT
2 bar.svcb.example.com. 120 IN A 192.0.2.1
2 bar.svcb.example.com. 120 IN AAAA 2001:db8::3:1
bar.svcb IN SVCB 1 . alpn=h2
bar.svcb IN SVCB 3 . alpn=h3 port=1500
bar.svcb IN SVCB 4 . alpn=h3 port="1501"
+bar.svcb IN SVCB 5 . port="8004" no-default-alpn dohpath=/dns-query{?dns} ohttp tls-supported-groups=29,23
+bar.svcb IN SVCB 6 . key00997="quoted" key0998=foo key999=bar
bar.svcb IN AAAA 2001:db8::3:1
bar.svcb IN AAAA 2001:db8::3:4
bar.svcb IN A 192.0.2.1