[fdio] Initial implementation of getifaddrs Sets up the API plumbing and implement getifaddrs to the point where a list of all addresses are returned. Due to lack of support in the current version of the netstack, broadcast address (missing IFF_BROADCAST flag) and destination address are not set. They will be added when corresponding support is added in the netstack. Support for AF_PACKET addresses will be added separately. Test: fx test -d getifaddrs-netemul-test fx test --host getifaddrs-test Bug: 30719, 54162, 54163 Change-Id: I52910b5bbf5a4d493fd9b591e1dbb2203aa51ef9 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/398773 Commit-Queue: Jay Zhuang <jayzhuang@google.com> Reviewed-by: Tamir Duberstein <tamird@google.com> Reviewed-by: Adam Barth <abarth@google.com> Reviewed-by: Chris Tam <godtamit@google.com> Testability-Review: Tamir Duberstein <tamird@google.com> API-Review: Adam Barth <abarth@google.com>
diff --git a/sdk/fidl/fuchsia.net.stack/stack.fidl b/sdk/fidl/fuchsia.net.stack/stack.fidl index 49f179e..13f01fd 100644 --- a/sdk/fidl/fuchsia.net.stack/stack.fidl +++ b/sdk/fidl/fuchsia.net.stack/stack.fidl
@@ -46,6 +46,7 @@ 3: AdministrativeStatus administrative; }; +// TODO(https://fxbug.dev/54163): use `fuchsia.net.InterfaceAddress` instead. struct InterfaceAddress { /// The IP address of the interface. fuchsia.net.IpAddress ip_address;
diff --git a/sdk/fidl/fuchsia.net/net.fidl b/sdk/fidl/fuchsia.net/net.fidl index a47f8c7..9e761c1 100644 --- a/sdk/fidl/fuchsia.net/net.fidl +++ b/sdk/fidl/fuchsia.net/net.fidl
@@ -33,11 +33,11 @@ uint16 port; }; -/// Subnet describes an IP subnetwork, where all host IP addresses share the same most significant -/// bits. +// TODO(https://fxbug.dev/54163): rename Subnet to AddressWithPrefix when +// binding support is ready, so we don't have to recursively fix all users. +/// An IP address with its subnet prefix length. struct Subnet { - /// The Ipv4 or Ipv6 address. Only the `prefix_len` most significant bits may be set in `addr`; - /// all bits in the host portion of the address must be zero. + /// The Ipv4 or Ipv6 address. IpAddress addr; /// The prefix length of the netmask. E.g. for 192.168.1.0/24, the prefix
diff --git a/sdk/fidl/fuchsia.posix.socket/BUILD.gn b/sdk/fidl/fuchsia.posix.socket/BUILD.gn index 2d10404..e94afa9e 100644 --- a/sdk/fidl/fuchsia.posix.socket/BUILD.gn +++ b/sdk/fidl/fuchsia.posix.socket/BUILD.gn
@@ -8,5 +8,8 @@ sdk_category = "partner" api = "fuchsia.posix.socket.api" sources = [ "socket.fidl" ] - public_deps = [ "//sdk/fidl/fuchsia.io" ] + public_deps = [ + "//sdk/fidl/fuchsia.io", + "//sdk/fidl/fuchsia.net", + ] }
diff --git a/sdk/fidl/fuchsia.posix.socket/fuchsia.posix.socket.api b/sdk/fidl/fuchsia.posix.socket/fuchsia.posix.socket.api index 7c1cec4..733fdba 100644 --- a/sdk/fidl/fuchsia.posix.socket/fuchsia.posix.socket.api +++ b/sdk/fidl/fuchsia.posix.socket/fuchsia.posix.socket.api
@@ -1,3 +1,3 @@ { - "fidl/fuchsia.posix.socket": "43a271948d74960c04d7ff1aeadd087f" + "fidl/fuchsia.posix.socket": "a3ac470444e23f55ad16c4d05755c8b1" } \ No newline at end of file
diff --git a/sdk/fidl/fuchsia.posix.socket/socket.fidl b/sdk/fidl/fuchsia.posix.socket/socket.fidl index 9d47b74..159cafb 100644 --- a/sdk/fidl/fuchsia.posix.socket/socket.fidl +++ b/sdk/fidl/fuchsia.posix.socket/socket.fidl
@@ -5,6 +5,7 @@ library fuchsia.posix.socket; using fuchsia.io; +using fuchsia.net; using zx; /// Chosen to match `sizeof(struct sockaddr_storage)`. @@ -87,6 +88,19 @@ Accept(int16 flags) -> (StreamSocket s) error int32; }; +/// Holds information about an interface and its addresses. +table InterfaceAddresses { + /// ID of the interface. + 1: uint64 id; + /// Name of the interface. + 2: interface_name name; + /// Contains the interface flags, as returned by the SIOCGIFFLAGS ioctl + /// operation. + 3: uint32 flags; + /// All addresses currently assigned to the interface. + 4: vector<fuchsia.net.Subnet>:MAX addresses; +}; + /// Provider implements the POSIX sockets API. [Discoverable] protocol Provider { @@ -99,4 +113,8 @@ /// Looks up an interface by its name and returns its index. Returns `ZX_ERR_NOT_FOUND` if the /// specified name doesn't exist. InterfaceNameToIndex(interface_name name) -> (uint64 index) error zx.status; + + /// Requests a list of [`fuchsia.posix.socket.InterfaceAddresses`] + /// describing the network interfaces on the system. + GetInterfaceAddresses() -> (vector<InterfaceAddresses>:MAX interfaces); };
diff --git a/sdk/lib/fdio/bsdsocket.cc b/sdk/lib/fdio/bsdsocket.cc index 2540a82..3e1b3ff 100644 --- a/sdk/lib/fdio/bsdsocket.cc +++ b/sdk/lib/fdio/bsdsocket.cc
@@ -4,8 +4,10 @@ #include <fcntl.h> #include <fuchsia/net/llcpp/fidl.h> +#include <ifaddrs.h> #include <lib/fdio/fdio.h> #include <lib/fdio/io.h> +#include <net/if.h> #include <netdb.h> #include <poll.h> #include <sys/socket.h> @@ -504,3 +506,79 @@ } return 0; } + +// TODO(https://fxbug.dev/30719): set ifa_ifu.ifu_broadaddr and ifa_ifu.ifu_dstaddr. +// +// AF_PACKET addresses containing lower-level details about the interfaces are not included in the +// result list because raw sockets are not supported on Fuchsia. +__EXPORT +int getifaddrs(struct ifaddrs** ifap) { + fsocket::Provider::SyncClient* provider = nullptr; + zx_status_t status = fdio_get_socket_provider(&provider); + if (status != ZX_OK) { + return ERROR(status); + } + + auto response = provider->GetInterfaceAddresses(); + status = response.status(); + if (status != ZX_OK) { + return ERROR(status); + } + + for (const auto& iface : response.Unwrap()->interfaces) { + if (!iface.has_name() || !iface.has_addresses()) { + continue; + } + + const auto& if_name = iface.name(); + for (const auto& address : iface.addresses()) { + auto ifs = static_cast<struct ifaddrs_storage*>(calloc(1, sizeof(struct ifaddrs_storage))); + if (ifs == nullptr) { + return -1; + } + const size_t n = std::min(if_name.size(), sizeof(ifs->name)); + memcpy(ifs->name, if_name.data(), n); + ifs->name[n] = 0; + ifs->ifa.ifa_name = ifs->name; + + const auto& addr = address.addr; + const uint8_t prefix_len = address.prefix_len; + + switch (addr.which()) { + case fnet::IpAddress::Tag::kIpv4: { + const auto& addr_bytes = addr.ipv4().addr; + copy_addr(&ifs->ifa.ifa_addr, AF_INET, &ifs->addr, + const_cast<uint8_t*>(addr_bytes.data()), addr_bytes.size(), iface.id()); + gen_netmask(&ifs->ifa.ifa_netmask, AF_INET, &ifs->netmask, prefix_len); + break; + } + case fnet::IpAddress::Tag::kIpv6: { + const auto& addr_bytes = addr.ipv6().addr; + copy_addr(&ifs->ifa.ifa_addr, AF_INET6, &ifs->addr, + const_cast<uint8_t*>(addr_bytes.data()), addr_bytes.size(), iface.id()); + gen_netmask(&ifs->ifa.ifa_netmask, AF_INET6, &ifs->netmask, prefix_len); + break; + } + } + + if (iface.has_flags()) { + ifs->ifa.ifa_flags = iface.flags(); + } + + *ifap = &ifs->ifa; + ifap = &ifs->ifa.ifa_next; + } + } + + return 0; +} + +__EXPORT +void freeifaddrs(struct ifaddrs* ifp) { + struct ifaddrs* n; + while (ifp) { + n = ifp->ifa_next; + free(ifp); + ifp = n; + } +}
diff --git a/sdk/lib/fdio/fdio.symbols.api b/sdk/lib/fdio/fdio.symbols.api index 0e2a55d..d1f7851 100644 --- a/sdk/lib/fdio/fdio.symbols.api +++ b/sdk/lib/fdio/fdio.symbols.api
@@ -75,6 +75,7 @@ fdio_watch_directory fdio_zxio_create fdopendir +freeifaddrs fstat fstatat fstatfs @@ -83,6 +84,7 @@ ftruncate futimens getcwd +getifaddrs getpeername getsockname getsockopt
diff --git a/src/connectivity/network/netstack/fuchsia_posix_socket.go b/src/connectivity/network/netstack/fuchsia_posix_socket.go index 87091cd..b5182d9 100644 --- a/src/connectivity/network/netstack/fuchsia_posix_socket.go +++ b/src/connectivity/network/netstack/fuchsia_posix_socket.go
@@ -11,6 +11,7 @@ "net" "reflect" "runtime" + "sort" "strings" "sync" "sync/atomic" @@ -19,10 +20,13 @@ "syscall/zx/zxsocket" "syscall/zx/zxwait" + "go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/fidlconv" + "go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link" "go.fuchsia.dev/fuchsia/src/lib/component" syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go" "fidl/fuchsia/io" + fidlnet "fidl/fuchsia/net" "fidl/fuchsia/posix/socket" "gvisor.dev/gvisor/pkg/tcpip" @@ -43,6 +47,7 @@ #cgo CFLAGS: -I${SRCDIR}/../../../../zircon/third_party/ulib/musl/include #include <errno.h> #include <fcntl.h> +#include <net/if.h> #include <netinet/in.h> */ import "C" @@ -1276,6 +1281,71 @@ return socket.ProviderInterfaceNameToIndexResultWithErr(int32(zx.ErrNotFound)), nil } +func (sp *providerImpl) GetInterfaceAddresses(fidl.Context) ([]socket.InterfaceAddresses, error) { + nicInfos := sp.ns.stack.NICInfo() + + resultInfos := make([]socket.InterfaceAddresses, 0, len(nicInfos)) + for id, info := range nicInfos { + // Ensure deterministic API response. + sort.Slice(info.ProtocolAddresses, func(i, j int) bool { + x, y := info.ProtocolAddresses[i], info.ProtocolAddresses[j] + if x.Protocol != y.Protocol { + return x.Protocol < y.Protocol + } + ax, ay := x.AddressWithPrefix, y.AddressWithPrefix + if ax.Address != ay.Address { + return ax.Address < ay.Address + } + return ax.PrefixLen < ay.PrefixLen + }) + + addrs := make([]fidlnet.Subnet, 0, len(info.ProtocolAddresses)) + for _, a := range info.ProtocolAddresses { + if a.Protocol != ipv4.ProtocolNumber && a.Protocol != ipv6.ProtocolNumber { + continue + } + addrs = append(addrs, fidlnet.Subnet{ + Addr: fidlconv.ToNetIpAddress(a.AddressWithPrefix.Address), + PrefixLen: uint8(a.AddressWithPrefix.PrefixLen), + }) + } + + var resultInfo socket.InterfaceAddresses + resultInfo.SetId(uint64(id)) + resultInfo.SetName(info.Name) + resultInfo.SetAddresses(addrs) + + // gVisor assumes interfaces are always up, which is not the case on Fuchsia, + // so overwrite it with Fuchsia's interface state. + ifs := info.Context.(*ifState) + var bits uint32 + flags := info.Flags + if flags.Running { + bits |= C.IFF_RUNNING + } + if flags.Promiscuous { + bits |= C.IFF_PROMISC + } + if flags.Loopback { + bits |= C.IFF_LOOPBACK + } + ifs.mu.Lock() + if ifs.mu.state == link.StateStarted { + bits |= C.IFF_UP + } + ifs.mu.Unlock() + resultInfo.SetFlags(bits) + + resultInfos = append(resultInfos, resultInfo) + } + + // Ensure deterministic API response. + sort.Slice(resultInfos, func(i, j int) bool { + return resultInfos[i].Id < resultInfos[j].Id + }) + return resultInfos, nil +} + func tcpipErrorToCode(err *tcpip.Error) int32 { if err != tcpip.ErrConnectStarted { if pc, file, line, ok := runtime.Caller(1); ok {
diff --git a/src/connectivity/network/netstack3/src/bindings/socket/mod.rs b/src/connectivity/network/netstack3/src/bindings/socket/mod.rs index cb5f8da..1569ee0 100644 --- a/src/connectivity/network/netstack3/src/bindings/socket/mod.rs +++ b/src/connectivity/network/netstack3/src/bindings/socket/mod.rs
@@ -143,6 +143,10 @@ psocket::ProviderRequest::Socket2 { domain, type_, protocol: _, responder } => { responder_send!(responder, &mut self.socket(domain, type_)); } + psocket::ProviderRequest::GetInterfaceAddresses { responder } => { + // TODO(https://fxbug.dev/54162): implement this method. + responder_send!(responder, &mut std::iter::empty()); + } } }
diff --git a/src/connectivity/network/tests/BUILD.gn b/src/connectivity/network/tests/BUILD.gn index ec17a69..6925969 100644 --- a/src/connectivity/network/tests/BUILD.gn +++ b/src/connectivity/network/tests/BUILD.gn
@@ -20,6 +20,7 @@ ":netstack_external_network_test_client($host_toolchain)", ":netstack_if_nameindex_test($host_toolchain)", "benchmarks", + "getifaddrs:tests", "integration:tests", ] }
diff --git a/src/connectivity/network/tests/getifaddrs/BUILD.gn b/src/connectivity/network/tests/getifaddrs/BUILD.gn new file mode 100644 index 0000000..f2bbf34 --- /dev/null +++ b/src/connectivity/network/tests/getifaddrs/BUILD.gn
@@ -0,0 +1,41 @@ +# Copyright 2020 The Fuchsia Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/test.gni") +import("//src/sys/build/components.gni") + +test("getifaddrs-test") { + if (is_linux || is_fuchsia) { + sources = [ "getifaddrs_test.cc" ] + } + deps = [ "//src/lib/fxl/test:gtest_main" ] +} + +fuchsia_component("getifaddrs-test-component") { + testonly = true + manifest = "meta/getifaddrs-test.cmx" + deps = [ ":getifaddrs-test" ] +} + +fuchsia_component("getifaddrs-netemul-test") { + testonly = true + manifest = "meta/getifaddrs-netemul-test.cmx" + deps = [ ":getifaddrs-test-component" ] +} + +fuchsia_test_package("getifaddrs-tests") { + test_components = [ ":getifaddrs-netemul-test" ] +} + +group("tests") { + testonly = true + + deps = [ + ":getifaddrs-test($host_toolchain)", + ":getifaddrs-tests", + + # TODO(brunodalbo): move this to component level when netemul can handle it. + "//src/connectivity/network/testing/netemul", + ] +}
diff --git a/src/connectivity/network/tests/getifaddrs/getifaddrs_test.cc b/src/connectivity/network/tests/getifaddrs/getifaddrs_test.cc new file mode 100644 index 0000000..115acd5 --- /dev/null +++ b/src/connectivity/network/tests/getifaddrs/getifaddrs_test.cc
@@ -0,0 +1,136 @@ +// Copyright 2020 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <arpa/inet.h> +#include <errno.h> +#include <ifaddrs.h> +// <net/if.h> doesn't contain the full list of interface flags on Linux. +#if defined(__linux__) +#include <linux/if.h> +#else +#include <net/if.h> +#endif + +#include <algorithm> +#include <string> +#include <tuple> +#include <unordered_set> +#include <vector> + +#include <gtest/gtest.h> + +namespace { + +uint8_t count_prefix(const uint8_t* mask, size_t len) { + uint8_t l = 0; + for (size_t i = 0; i < len; i++) { + auto m = mask[i]; + for (size_t j = 0; j < sizeof(mask); j++) { + if (m) { + l++; + m <<= 1; + } else { + return l; + } + } + } + return l; +} + +TEST(GetIfAddrsTest, GetIfAddrsTest) { + const uint32_t unsupported_flags = IFF_BROADCAST | IFF_DEBUG | IFF_POINTOPOINT | IFF_NOTRAILERS | + IFF_NOARP | IFF_ALLMULTI | IFF_MASTER | IFF_SLAVE | + IFF_MULTICAST | IFF_PORTSEL | IFF_AUTOMEDIA | IFF_DYNAMIC | + IFF_LOWER_UP | IFF_DORMANT | IFF_ECHO; + + // Fields of this tuple are: interface_name, address, prefix_length, scope_id, flags. + using InterfaceAddress = std::tuple<std::string, std::string, uint8_t, uint32_t, uint32_t>; + + std::vector<InterfaceAddress> want_ifaddrs{ + std::make_tuple("lo", "127.0.0.1", 8, 0, IFF_LOOPBACK | IFF_UP | IFF_RUNNING), + std::make_tuple("lo", "::1", 128, 0, IFF_LOOPBACK | IFF_UP | IFF_RUNNING), + }; + const size_t lo_addrs_count = want_ifaddrs.size(); + +#if defined(__Fuchsia__) + want_ifaddrs.push_back(std::make_tuple("ep1", "192.168.0.1", 20, 0, IFF_UP | IFF_RUNNING)); + want_ifaddrs.push_back(std::make_tuple("ep2", "192.168.0.2", 15, 0, IFF_UP | IFF_RUNNING)); + want_ifaddrs.push_back(std::make_tuple("ep3", "fe80::1", 64, 4, IFF_UP | IFF_RUNNING)); + want_ifaddrs.push_back(std::make_tuple("ep4", "1234::5:6:7:8", 120, 0, IFF_UP | IFF_RUNNING)); +#endif + + struct ifaddrs* ifaddr; + ASSERT_EQ(getifaddrs(&ifaddr), 0) << strerror(errno); + + std::vector<InterfaceAddress> got_ifaddrs; + // Expect one auto-generated link-local address per non-loopback interface. + const size_t want_unknown_link_local_addrs = want_ifaddrs.size() - lo_addrs_count; + size_t got_unknown_link_local_addrs = 0; + + for (auto it = ifaddr; it != nullptr; it = it->ifa_next) { + const auto if_name = std::string(it->ifa_name); +#if defined(__linux__) + // Only loopback is consistent on host environments. + if (if_name != "lo") { + continue; + } +#endif + + switch (it->ifa_addr->sa_family) { + case AF_INET: { + struct sockaddr_in* addr_in = reinterpret_cast<sockaddr_in*>(it->ifa_addr); + char sin_addr_buf[INET_ADDRSTRLEN]; + const char* sin_addr = + inet_ntop(AF_INET, &addr_in->sin_addr, sin_addr_buf, INET_ADDRSTRLEN); + + const sockaddr_in* netmask = reinterpret_cast<sockaddr_in*>(it->ifa_netmask); + const uint8_t prefix_len = + count_prefix(reinterpret_cast<const uint8_t*>(&netmask->sin_addr.s_addr), 4); + + got_ifaddrs.push_back(std::make_tuple(if_name, std::string(sin_addr), prefix_len, 0, + it->ifa_flags & ~unsupported_flags)); + break; + } + case AF_INET6: { + struct sockaddr_in6* addr_in6 = reinterpret_cast<sockaddr_in6*>(it->ifa_addr); + char sin6_addr_buf[INET6_ADDRSTRLEN]; + const char* sin6_addr = + inet_ntop(AF_INET6, &(addr_in6->sin6_addr), sin6_addr_buf, INET6_ADDRSTRLEN); + + const std::string sin6_addr_str = std::string(sin6_addr); + + const bool is_known_addr = std::any_of(want_ifaddrs.begin(), want_ifaddrs.end(), + [sin6_addr_str](const InterfaceAddress& ifaddr) { + return std::get<1>(ifaddr) == sin6_addr_str; + }); + + // Skip and count auto-generated link-local addresses. + if (IN6_IS_ADDR_LINKLOCAL(addr_in6->sin6_addr.s6_addr) && !is_known_addr) { + got_unknown_link_local_addrs++; + continue; + } + + const sockaddr_in6* netmask = reinterpret_cast<sockaddr_in6*>(it->ifa_netmask); + const uint8_t prefix_len = count_prefix(netmask->sin6_addr.s6_addr, 16); + + got_ifaddrs.push_back(std::make_tuple(if_name, sin6_addr_str, prefix_len, + addr_in6->sin6_scope_id, + it->ifa_flags & ~unsupported_flags)); + break; + } + case AF_PACKET: + // Ignore AF_PACKET addresses because raw sockets are not supported on Fuchsia. + continue; + default: + GTEST_FAIL() << "unexpected address family " << it->ifa_addr->sa_family; + } + } + + EXPECT_EQ(got_ifaddrs, want_ifaddrs); + EXPECT_EQ(got_unknown_link_local_addrs, want_unknown_link_local_addrs); + + freeifaddrs(ifaddr); +} + +} // namespace
diff --git a/src/connectivity/network/tests/getifaddrs/meta/getifaddrs-netemul-test.cmx b/src/connectivity/network/tests/getifaddrs/meta/getifaddrs-netemul-test.cmx new file mode 100644 index 0000000..a742b2f --- /dev/null +++ b/src/connectivity/network/tests/getifaddrs/meta/getifaddrs-netemul-test.cmx
@@ -0,0 +1,78 @@ +{ + "facets": { + "fuchsia.netemul": { + "environment": { + "services": { + "fuchsia.net.stack.Stack": "fuchsia-pkg://fuchsia.com/netstack#meta/netstack_debug.cmx", + "fuchsia.netstack.Netstack": "fuchsia-pkg://fuchsia.com/netstack#meta/netstack_debug.cmx", + "fuchsia.posix.socket.Provider": "fuchsia-pkg://fuchsia.com/netstack#meta/netstack_debug.cmx" + }, + "setup": [ + { + "arguments": [ + "-e", + "ep1", + "-i", + "192.168.0.1/20" + ], + "url": "fuchsia-pkg://fuchsia.com/netemul_sandbox#meta/helper_netstack_cfg.cmx" + }, + { + "arguments": [ + "-e", + "ep2", + "-i", + "192.168.0.2/15" + ], + "url": "fuchsia-pkg://fuchsia.com/netemul_sandbox#meta/helper_netstack_cfg.cmx" + }, + { + "arguments": [ + "-e", + "ep3", + "-i", + "fe80::1/64" + ], + "url": "fuchsia-pkg://fuchsia.com/netemul_sandbox#meta/helper_netstack_cfg.cmx" + }, + { + "arguments": [ + "-e", + "ep4", + "-i", + "1234::5:6:7:8/120" + ], + "url": "fuchsia-pkg://fuchsia.com/netemul_sandbox#meta/helper_netstack_cfg.cmx" + } + ], + "test": [ + "fuchsia-pkg://fuchsia.com/getifaddrs-tests#meta/getifaddrs-test-component.cmx" + ] + }, + "networks": [ + { + "endpoints": [ + { + "name": "ep1" + }, + { + "name": "ep2" + }, + { + "name": "ep3" + }, + { + "name": "ep4" + } + ], + "name": "net" + } + ], + "timeout": 120 + } + }, + "program": { + "binary": "test/getifaddrs-netemul-test" + }, + "runner": "fuchsia-pkg://fuchsia.com/netemul_runner#meta/netemul_runner.cmx" +}
diff --git a/src/connectivity/network/tests/getifaddrs/meta/getifaddrs-test.cmx b/src/connectivity/network/tests/getifaddrs/meta/getifaddrs-test.cmx new file mode 100644 index 0000000..2c1aba7 --- /dev/null +++ b/src/connectivity/network/tests/getifaddrs/meta/getifaddrs-test.cmx
@@ -0,0 +1,11 @@ +{ + "program": { + "binary": "test/getifaddrs-test" + }, + "sandbox": { + "services": [ + "fuchsia.net.stack.Stack", + "fuchsia.posix.socket.Provider" + ] + } +}
diff --git a/zircon/third_party/ulib/musl/src/network/getifaddrs.c b/zircon/third_party/ulib/musl/src/network/getifaddrs.c index 7ca9a6e..70bf1a5 100644 --- a/zircon/third_party/ulib/musl/src/network/getifaddrs.c +++ b/zircon/third_party/ulib/musl/src/network/getifaddrs.c
@@ -2,15 +2,6 @@ #include "getifaddrs.h" -void freeifaddrs(struct ifaddrs* ifp) { - struct ifaddrs* n; - while (ifp) { - n = ifp->ifa_next; - free(ifp); - ifp = n; - } -} - static int netlink_msg_to_ifaddr(void* pctx, struct nlmsghdr* h) { struct ifaddrs_ctx* ctx = pctx; struct ifaddrs_storage *ifs, *ifs0 = NULL; @@ -122,15 +113,3 @@ } return 0; } - -int getifaddrs(struct ifaddrs** ifap) { - struct ifaddrs_ctx _ctx, *ctx = &_ctx; - int r; - memset(ctx, 0, sizeof *ctx); - r = __rtnetlink_enumerate(AF_UNSPEC, AF_UNSPEC, netlink_msg_to_ifaddr, ctx); - if (r == 0) - *ifap = &ctx->first->ifa; - else - freeifaddrs(&ctx->first->ifa); - return r; -}
diff --git a/zircon/third_party/ulib/musl/stubs/socketstubs.c b/zircon/third_party/ulib/musl/stubs/socketstubs.c index 5ca3cf2..429c835 100644 --- a/zircon/third_party/ulib/musl/stubs/socketstubs.c +++ b/zircon/third_party/ulib/musl/stubs/socketstubs.c
@@ -1,5 +1,6 @@ #define _GNU_SOURCE #include <errno.h> +#include <ifaddrs.h> #include <netdb.h> #include <sys/socket.h> #include <sys/types.h> @@ -118,3 +119,12 @@ return -1; } weak_alias(stub_sockatmark, sockatmark); + +static int stub_getifaddrs(struct ifaddrs** ifap) { + errno = ENOSYS; + return -1; +} +weak_alias(stub_getifaddrs, getifaddrs); + +static void stub_freeifaddrs(struct ifaddrs* ifp) {} +weak_alias(stub_freeifaddrs, freeifaddrs);