[fuchsia] migrate from ioctls to FIDL

Bug: https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=6250
Change-Id: If2756bca0b226bfe8e89b4c793933abac540801e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/117620
Commit-Queue: Zach Anderson <zra@google.com>
Auto-Submit: Tamir Duberstein <tamird@google.com>
Reviewed-by: Zach Anderson <zra@google.com>
Reviewed-by: Chinmay Garde <chinmaygarde@google.com>
This commit is contained in:
Tamir Duberstein 2019-09-17 22:17:08 +00:00 committed by commit-bot@chromium.org
parent cb80ea7ba9
commit 085f81224a
2 changed files with 73 additions and 66 deletions

View file

@ -266,12 +266,12 @@ template("build_gen_snapshot_dart_io") {
if (is_fuchsia) {
if (using_fuchsia_sdk) {
deps += [ "$fuchsia_sdk_root/pkg/lib/netstack/c" ]
deps += [ "$fuchsia_sdk_root/fidl:fuchsia.netstack" ]
public_deps = [
"$fuchsia_sdk_root/pkg:fdio",
]
} else {
deps += [ "//garnet/public/lib/netstack/c" ]
deps += [ "//sdk/fidl/fuchsia.netstack" ]
public_deps = [
"//zircon/public/lib/fdio",
]
@ -388,12 +388,12 @@ template("dart_io") {
if (is_fuchsia) {
if (using_fuchsia_sdk) {
deps += [ "$fuchsia_sdk_root/pkg/lib/netstack/c" ]
deps += [ "$fuchsia_sdk_root/fidl:fuchsia.netstack" ]
public_deps = [
"$fuchsia_sdk_root/pkg:fdio",
]
} else {
deps += [ "//garnet/public/lib/netstack/c" ]
deps += [ "//sdk/fidl/fuchsia.netstack" ]
public_deps = [
"//zircon/public/lib/fdio",
]

View file

@ -7,20 +7,18 @@
#include "bin/socket_base.h"
// TODO(ZX-766): If/when Fuchsia adds getifaddrs(), use that instead of the
// ioctl in netconfig.h.
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
#include <ifaddrs.h> // NOLINT
#include <lib/netstack/c/netconfig.h>
#include <net/if.h> // NOLINT
#include <netinet/tcp.h> // NOLINT
#include <stdio.h> // NOLINT
#include <stdlib.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/ioctl.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
#include <errno.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <ifaddrs.h>
#include <lib/sys/cpp/service_directory.h>
#include <net/if.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>
#include "bin/eventhandler.h"
#include "bin/fdutils.h"
@ -66,9 +64,20 @@ SocketAddress::SocketAddress(struct sockaddr* sa) {
memmove(reinterpret_cast<void*>(&addr_), sa, salen);
}
static fidl::SynchronousInterfacePtr<fuchsia::netstack::Netstack> netstack;
static zx_status_t status;
static std::once_flag once;
bool SocketBase::Initialize() {
// Nothing to do on Fuchsia.
return true;
std::call_once(once, [&]() {
auto directory = sys::ServiceDirectory::CreateFromNamespace();
status = directory->Connect(netstack.NewRequest());
if (status != ZX_OK) {
LOG_ERR("Initialize: connecting to fuchsia.netstack failed: %s\n",
zx_status_get_string(status));
}
});
return status == ZX_OK;
}
bool SocketBase::FormatNumericAddress(const RawAddr& addr,
@ -264,13 +273,6 @@ bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) {
return (result == 1);
}
static bool ShouldIncludeIfaAddrs(netc_if_info_t* if_info, int lookup_family) {
const int family = if_info->addr.ss_family;
return ((lookup_family == family) ||
(((lookup_family == AF_UNSPEC) &&
((family == AF_INET) || (family == AF_INET6)))));
}
bool SocketBase::ListInterfacesSupported() {
return true;
}
@ -278,54 +280,59 @@ bool SocketBase::ListInterfacesSupported() {
AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
int type,
OSError** os_error) {
// We need a dummy socket.
const int fd = socket(AF_INET6, SOCK_STREAM, 0);
if (fd < 0) {
LOG_ERR("ListInterfaces: socket(AF_INET, SOCK_DGRAM, 0) failed\n");
std::vector<fuchsia::netstack::NetInterface2> interfaces;
zx_status_t status = netstack->GetInterfaces2(&interfaces);
if (status != ZX_OK) {
LOG_ERR("ListInterfaces: fuchsia.netstack.GetInterfaces2 failed: %s\n",
zx_status_get_string(status));
errno = EIO;
return NULL;
}
// Call the ioctls.
netc_get_if_info_t get_if_info;
const ssize_t size = ioctl_netc_get_num_ifs(fd, &get_if_info.n_info);
if (size < 0) {
LOG_ERR("ListInterfaces: ioctl_netc_get_num_ifs() failed");
close(fd);
return NULL;
}
for (uint32_t i = 0; i < get_if_info.n_info; i++) {
const ssize_t size =
ioctl_netc_get_if_info_at(fd, &i, &get_if_info.info[i]);
if (size < 0) {
LOG_ERR("ListInterfaces: ioctl_netc_get_if_info_at() failed");
close(fd);
return NULL;
}
}
// Process the results.
const int lookup_family = SocketAddress::FromType(type);
intptr_t count = 0;
for (intptr_t i = 0; i < get_if_info.n_info; i++) {
if (ShouldIncludeIfaAddrs(&get_if_info.info[i], lookup_family)) {
count++;
}
}
AddressList<InterfaceSocketAddress>* addresses =
new AddressList<InterfaceSocketAddress>(count);
std::remove_if(
interfaces.begin(), interfaces.end(),
[lookup_family](const auto& interface) {
switch (interface.addr.Which()) {
case fuchsia::net::IpAddress::Tag::kIpv4:
return !(lookup_family == AF_UNSPEC || lookup_family == AF_INET);
case fuchsia::net::IpAddress::Tag::kIpv6:
return !(lookup_family == AF_UNSPEC || lookup_family == AF_INET6);
case fuchsia::net::IpAddress::Tag::Invalid:
return true;
}
});
auto addresses = new AddressList<InterfaceSocketAddress>(interfaces.size());
int addresses_idx = 0;
for (intptr_t i = 0; i < get_if_info.n_info; i++) {
if (ShouldIncludeIfaAddrs(&get_if_info.info[i], lookup_family)) {
char* ifa_name = DartUtils::ScopedCopyCString(get_if_info.info[i].name);
InterfaceSocketAddress* isa = new InterfaceSocketAddress(
reinterpret_cast<struct sockaddr*>(&get_if_info.info[i].addr),
ifa_name, if_nametoindex(get_if_info.info[i].name));
addresses->SetAt(addresses_idx, isa);
addresses_idx++;
for (const auto& interface : interfaces) {
struct sockaddr_storage addr = {};
auto addr_in = reinterpret_cast<struct sockaddr_in*>(&addr);
auto addr_in6 = reinterpret_cast<struct sockaddr_in6*>(&addr);
switch (interface.addr.Which()) {
case fuchsia::net::IpAddress::Tag::kIpv4:
addr_in->sin_family = AF_INET;
memmove(&addr_in->sin_addr, interface.addr.ipv4().addr.data(),
sizeof(addr_in->sin_addr));
break;
case fuchsia::net::IpAddress::Tag::kIpv6:
addr_in6->sin6_family = AF_INET6;
memmove(&addr_in6->sin6_addr, interface.addr.ipv6().addr.data(),
sizeof(addr_in6->sin6_addr));
break;
case fuchsia::net::IpAddress::Tag::Invalid:
// Should have been filtered out above.
UNREACHABLE();
}
addresses->SetAt(addresses_idx,
new InterfaceSocketAddress(
reinterpret_cast<sockaddr*>(&addr),
DartUtils::ScopedCopyCString(interface.name.c_str()),
if_nametoindex(interface.name.c_str())));
addresses_idx++;
}
close(fd);
return addresses;
}