diff --git a/db/system_keyspace.cc b/db/system_keyspace.cc index 0a0c580805..ed8a7addf6 100644 --- a/db/system_keyspace.cc +++ b/db/system_keyspace.cc @@ -68,6 +68,7 @@ #include "log.hh" #include "serializer.hh" #include +#include #include "service/storage_proxy.hh" #include "message/messaging_service.hh" #include "mutation_query.hh" @@ -996,8 +997,7 @@ static distributed _local_cache; static future<> build_dc_rack_info() { return execute_cql(sprint("SELECT peer, data_center, rack from system.%s", PEERS)).then([] (::shared_ptr msg) { return do_for_each(*msg, [] (auto& row) { - // Not ideal to assume ipv4 here, but currently this is what the cql types wraps. - net::ipv4_address peer = row.template get_as("peer"); + net::inet_address peer = row.template get_as("peer"); if (!row.has("data_center") || !row.has("rack")) { return make_ready_future<>(); } @@ -1299,7 +1299,7 @@ future>> lo return execute_cql(req).then([] (::shared_ptr cql_result) { std::unordered_map> ret; for (auto& row : *cql_result) { - auto peer = gms::inet_address(row.get_as("peer")); + auto peer = gms::inet_address(row.get_as("peer")); if (row.has("tokens")) { auto blob = row.get_blob("tokens"); auto cdef = peers()->get_column_definition("tokens"); @@ -1317,7 +1317,7 @@ future> load_host_ids() { return execute_cql(req).then([] (::shared_ptr cql_result) { std::unordered_map ret; for (auto& row : *cql_result) { - auto peer = gms::inet_address(row.get_as("peer")); + auto peer = gms::inet_address(row.get_as("peer")); if (row.has("host_id")) { ret.emplace(peer, row.get_as("host_id")); } @@ -1332,7 +1332,7 @@ future> load_peer_features() { std::unordered_map ret; for (auto& row : *cql_result) { if (row.has("supported_features")) { - ret.emplace(row.get_as("peer"), + ret.emplace(row.get_as("peer"), row.get_as("supported_features")); } } @@ -1354,8 +1354,8 @@ future> get_preferred_i for (auto& r : *cql_res_set) { if (r.has("preferred_ip")) { - res.emplace(gms::inet_address(r.get_as("peer")), - gms::inet_address(r.get_as("preferred_ip"))); + res.emplace(gms::inet_address(r.get_as("peer")), + gms::inet_address(r.get_as("preferred_ip"))); } } diff --git a/gms/inet_address.cc b/gms/inet_address.cc index cc3354b0bc..a9db62e4dd 100644 --- a/gms/inet_address.cc +++ b/gms/inet_address.cc @@ -37,11 +37,18 @@ */ #include +#include +#include #include "inet_address.hh" +using namespace seastar; + +gms::inet_address::inet_address(const net::inet_address& in) + : inet_address(in.as_ipv4_address()) +{} + future gms::inet_address::lookup(sstring name) { return seastar::net::inet_address::find(name, seastar::net::inet_address::family::INET).then([](seastar::net::inet_address&& a) { - ::in_addr in = a; - return make_ready_future(net::ntoh(in.s_addr)); + return make_ready_future(a); }); } diff --git a/gms/inet_address.hh b/gms/inet_address.hh index 58f0a26f85..7b97f1eadd 100644 --- a/gms/inet_address.hh +++ b/gms/inet_address.hh @@ -25,6 +25,10 @@ #include "utils/serialization.hh" #include +namespace seastar::net { + class inet_address; +} + namespace gms { class inet_address { @@ -49,11 +53,15 @@ public: throw std::invalid_argument("IPv6 socket addresses are not supported."); } } + // Note: for now, will throw if given an ipv6 address + inet_address(const seastar::net::inet_address&); const net::ipv4_address& addr() const { return _addr; } + operator seastar::net::inet_address() const; + inet_address(const sstring& addr) { // FIXME: We need a real DNS resolver if (addr == "localhost") { diff --git a/tests/cql_query_test.cc b/tests/cql_query_test.cc index 986c6866df..4a64a7e8bf 100644 --- a/tests/cql_query_test.cc +++ b/tests/cql_query_test.cc @@ -26,6 +26,8 @@ #include #include +#include + #include "tests/test-utils.hh" #include "tests/cql_test_env.hh" #include "tests/cql_assertions.hh" @@ -1586,7 +1588,7 @@ SEASTAR_TEST_CASE(test_types) { ascii_type->decompose(sstring("ascii")), long_type->decompose(123456789l), from_hex("deadbeef"), boolean_type->decompose(true), double_type->decompose(3.14), float_type->decompose(3.14f), - inet_addr_type->decompose(net::ipv4_address("127.0.0.1")), + inet_addr_type->decompose(net::inet_address("127.0.0.1")), int32_type->decompose(3), utf8_type->decompose(sstring("zażółć gęślą jaźń")), timestamp_type->decompose(tp), timeuuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))), @@ -1638,7 +1640,7 @@ SEASTAR_TEST_CASE(test_types) { ascii_type->decompose(sstring("ascii2")), long_type->decompose(123456789l), from_hex("000000000000000c"), boolean_type->decompose(true), double_type->decompose(3.14), float_type->decompose(3.14f), - inet_addr_type->decompose(net::ipv4_address("127.0.0.1")), + inet_addr_type->decompose(net::inet_address("127.0.0.1")), int32_type->decompose(3), utf8_type->decompose(sstring("zażółć gęślą jaźń")), timestamp_type->decompose(tp), timeuuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))), @@ -2789,7 +2791,7 @@ SEASTAR_TEST_CASE(test_insert_json_types) { assert_that(msg).is_rows().with_rows({ { ascii_type->decompose(sstring("ascii")), - inet_addr_type->decompose(net::ipv4_address("127.0.0.1")), // note - case-sensitive columns go right after the key + inet_addr_type->decompose(net::inet_address("127.0.0.1")), // note - case-sensitive columns go right after the key int32_type->decompose(3), utf8_type->decompose(sstring("zażółć gęślą jaźń")), long_type->decompose(123456789l), from_hex("deadbeef"), boolean_type->decompose(true), diff --git a/tests/sstable_mutation_test.cc b/tests/sstable_mutation_test.cc index 779242cc42..43e571c8b6 100644 --- a/tests/sstable_mutation_test.cc +++ b/tests/sstable_mutation_test.cc @@ -21,6 +21,7 @@ #include +#include #include "tests/test-utils.hh" #include "sstable_test.hh" #include "sstables/key.hh" @@ -506,7 +507,7 @@ SEASTAR_TEST_CASE(broken_ranges_collection) { return repeat([s, reader] { return read_mutation_from_flat_mutation_reader(*reader).then([s, reader] (mutation_opt mut) { auto key_equal = [s, &mut] (sstring ip) { - return mut->key().equal(*s, partition_key::from_deeply_exploded(*s, { net::ipv4_address(ip) })); + return mut->key().equal(*s, partition_key::from_deeply_exploded(*s, { net::inet_address(ip) })); }; if (!mut) { diff --git a/tests/types_test.cc b/tests/types_test.cc index 25c2cc1218..8f16b0f575 100644 --- a/tests/types_test.cc +++ b/tests/types_test.cc @@ -20,6 +20,7 @@ */ #include +#include #include #include #include @@ -220,7 +221,7 @@ BOOST_AUTO_TEST_CASE(test_uuid_type_string_conversions) { } BOOST_AUTO_TEST_CASE(test_inet_type_string_conversions) { - net::ipv4_address addr("127.0.0.1"); + net::inet_address addr("127.0.0.1"); BOOST_REQUIRE(inet_addr_type->equal(inet_addr_type->from_string("127.0.0.1"), inet_addr_type->decompose(addr))); test_parsing_fails(inet_addr_type, "something"); diff --git a/types.cc b/types.cc index 654e0c14bb..32a1f1f0f1 100644 --- a/types.cc +++ b/types.cc @@ -45,6 +45,7 @@ #include #include #include +#include #include "utils/big_decimal.hh" #include "utils/date.h" #include "mutation_partition.hh" @@ -78,7 +79,7 @@ sstring boolean_to_string(const bool b) { return b ? "true" : "false"; } -sstring inet_to_string(const net::ipv4_address& addr) { +sstring inet_to_string(const seastar::net::inet_address& addr) { std::ostringstream out; out << addr; return out.str(); @@ -1168,39 +1169,59 @@ struct uuid_type_impl : concrete_type { } }; -struct inet_addr_type_impl : concrete_type { - inet_addr_type_impl() : concrete_type(inet_addr_type_name) {} +using inet_address = seastar::net::inet_address; + +struct inet_addr_type_impl : concrete_type { + inet_addr_type_impl() : concrete_type(inet_addr_type_name) {} virtual void serialize(const void* value, bytes::iterator& out) const override { if (!value) { return; } // FIXME: support ipv6 - auto& ipv4e = from_value(value); - if (ipv4e.empty()) { + auto& ipv = from_value(value); + if (ipv.empty()) { return; } - auto& ipv4 = ipv4e.get(); - uint32_t u = htonl(ipv4.ip); - out = std::copy_n(reinterpret_cast(&u), sizeof(u), out); + auto& ip = ipv.get(); + switch (ip.in_family()) { + case inet_address::family::INET: + { + const ::in_addr& in = ip; + out = std::copy_n(reinterpret_cast(&in.s_addr), sizeof(in.s_addr), out); + break; + } + case inet_address::family::INET6: + { + const ::in6_addr& i6 = ip; + out = std::copy_n(i6.s6_addr, ip.size(), out); + break; + } + } } virtual size_t serialized_size(const void* value) const override { - if (!value || from_value(value).empty()) { + if (!value) { return 0; } - return 4; + // FIXME: support ipv6 + auto& ipv = from_value(value); + if (ipv.empty()) { + return 0; + } + return ipv.get().size(); } virtual data_value deserialize(bytes_view v) const override { if (v.empty()) { return make_empty(); } - if (v.size() == 16) { - throw std::runtime_error("IPv6 addresses not supported"); + switch (v.size()) { + case 4: + // gah. read_simple_be, please... + return make_value(inet_address(::in_addr{net::hton(read_simple(v))})); + case 16: + return make_value(inet_address(*reinterpret_cast(v.data()))); + default: + throw marshal_exception(sprint("Cannot deserialize inet_address, unsupported size %d bytes", v.size())); } - auto ip = read_simple(v); - if (!v.empty()) { - throw marshal_exception(sprint("Cannot deserialize inet_addr, %d bytes left", v.size())); - } - return make_value(net::ipv4_address(ip)); } virtual bool less(bytes_view v1, bytes_view v2) const override { return less_unsigned(v1, v2); @@ -1215,7 +1236,7 @@ struct inet_addr_type_impl : concrete_type { return std::hash()(v); } virtual void validate(bytes_view v) const override { - if (v.size() != 0 && v.size() != sizeof(uint32_t)) { + if (v.size() != 0 && v.size() != sizeof(uint32_t) && v.size() != 16) { throw marshal_exception(sprint("Validation failed for inet_addr - got %d bytes", v.size())); } } @@ -1224,15 +1245,15 @@ struct inet_addr_type_impl : concrete_type { if (s.empty()) { return bytes(); } - native_type ipv4; + native_type ip; try { - ipv4 = net::ipv4_address(std::string(s.data(), s.size())); + ip = inet_address(std::string(s.data(), s.size())); } catch (...) { throw marshal_exception(sprint("Failed to parse inet_addr from '%s'", s)); } - bytes b(bytes::initialized_later(), sizeof(uint32_t)); + bytes b(bytes::initialized_later(), ip.get().size()); auto out = b.begin(); - serialize(&ipv4, out); + serialize(&ip, out); return b; } virtual sstring to_string(const bytes& b) const override { @@ -3648,7 +3669,10 @@ data_value::data_value(float v) : data_value(make_new(float_type, v)) { data_value::data_value(double v) : data_value(make_new(double_type, v)) { } -data_value::data_value(net::ipv4_address v) : data_value(make_new(inet_addr_type, v)) { +data_value::data_value(seastar::net::inet_address v) : data_value(make_new(inet_addr_type, v)) { +} + +data_value::data_value(seastar::net::ipv4_address v) : data_value(seastar::net::inet_address(v)) { } data_value::data_value(simple_date_native_type v) : data_value(make_new(simple_date_type, v.days)) { @@ -3867,7 +3891,7 @@ std::function make_castas_fctn_from_boolean_to_string() std::function make_castas_fctn_from_inet_to_string() { return [](data_value from) -> data_value { - return inet_to_string(value_cast(from)); + return inet_to_string(value_cast(from)); }; } diff --git a/types.hh b/types.hh index dbf361a897..5ed2e94603 100644 --- a/types.hh +++ b/types.hh @@ -44,6 +44,7 @@ #include #include #include "net/ip.hh" +#include #include "util/backtrace.hh" #include "hashing.hh" #include // FIXME: remove somehow @@ -374,6 +375,7 @@ public: data_value(float); data_value(double); data_value(net::ipv4_address); + data_value(seastar::net::inet_address); data_value(simple_date_native_type); data_value(timestamp_native_type); data_value(timeuuid_native_type); @@ -1283,7 +1285,7 @@ shared_ptr data_type_for() { template <> inline -shared_ptr data_type_for() { +shared_ptr data_type_for() { return inet_addr_type; }