|
7 | 7 |
|
8 | 8 | #include "bin/socket_base.h"
|
9 | 9 |
|
10 |
| -#include <errno.h> |
11 |
| -#include <fuchsia/netstack/cpp/fidl.h> |
12 |
| -#include <ifaddrs.h> |
13 |
| -#include <lib/sys/cpp/service_directory.h> |
14 |
| -#include <net/if.h> |
15 |
| -#include <netinet/tcp.h> |
16 |
| -#include <stdio.h> |
17 |
| -#include <stdlib.h> |
18 |
| -#include <string.h> |
19 |
| -#include <sys/stat.h> |
20 |
| -#include <unistd.h> |
21 |
| -#include <vector> |
| 10 | +// TODO(ZX-766): If/when Fuchsia adds getifaddrs(), use that instead of the |
| 11 | +// ioctl in netconfig.h. |
| 12 | +#include <errno.h> // NOLINT |
| 13 | +#include <fcntl.h> // NOLINT |
| 14 | +#include <ifaddrs.h> // NOLINT |
| 15 | +#include <lib/netstack/c/netconfig.h> |
| 16 | +#include <net/if.h> // NOLINT |
| 17 | +#include <netinet/tcp.h> // NOLINT |
| 18 | +#include <stdio.h> // NOLINT |
| 19 | +#include <stdlib.h> // NOLINT |
| 20 | +#include <string.h> // NOLINT |
| 21 | +#include <sys/ioctl.h> // NOLINT |
| 22 | +#include <sys/stat.h> // NOLINT |
| 23 | +#include <unistd.h> // NOLINT |
22 | 24 |
|
23 | 25 | #include "bin/eventhandler.h"
|
24 | 26 | #include "bin/fdutils.h"
|
@@ -64,20 +66,9 @@ SocketAddress::SocketAddress(struct sockaddr* sa) {
|
64 | 66 | memmove(reinterpret_cast<void*>(&addr_), sa, salen);
|
65 | 67 | }
|
66 | 68 |
|
67 |
| -static fidl::SynchronousInterfacePtr<fuchsia::netstack::Netstack> netstack; |
68 |
| -static zx_status_t status; |
69 |
| -static std::once_flag once; |
70 |
| - |
71 | 69 | bool SocketBase::Initialize() {
|
72 |
| - std::call_once(once, [&]() { |
73 |
| - auto directory = sys::ServiceDirectory::CreateFromNamespace(); |
74 |
| - status = directory->Connect(netstack.NewRequest()); |
75 |
| - if (status != ZX_OK) { |
76 |
| - LOG_ERR("Initialize: connecting to fuchsia.netstack failed: %s\n", |
77 |
| - zx_status_get_string(status)); |
78 |
| - } |
79 |
| - }); |
80 |
| - return status == ZX_OK; |
| 70 | + // Nothing to do on Fuchsia. |
| 71 | + return true; |
81 | 72 | }
|
82 | 73 |
|
83 | 74 | bool SocketBase::FormatNumericAddress(const RawAddr& addr,
|
@@ -273,66 +264,68 @@ bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) {
|
273 | 264 | return (result == 1);
|
274 | 265 | }
|
275 | 266 |
|
| 267 | +static bool ShouldIncludeIfaAddrs(netc_if_info_t* if_info, int lookup_family) { |
| 268 | + const int family = if_info->addr.ss_family; |
| 269 | + return ((lookup_family == family) || |
| 270 | + (((lookup_family == AF_UNSPEC) && |
| 271 | + ((family == AF_INET) || (family == AF_INET6))))); |
| 272 | +} |
| 273 | + |
276 | 274 | bool SocketBase::ListInterfacesSupported() {
|
277 | 275 | return true;
|
278 | 276 | }
|
279 | 277 |
|
280 | 278 | AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
|
281 | 279 | int type,
|
282 | 280 | OSError** os_error) {
|
283 |
| - std::vector<fuchsia::netstack::NetInterface2> interfaces; |
284 |
| - zx_status_t status = netstack->GetInterfaces2(&interfaces); |
285 |
| - if (status != ZX_OK) { |
286 |
| - LOG_ERR("ListInterfaces: fuchsia.netstack.GetInterfaces2 failed: %s\n", |
287 |
| - zx_status_get_string(status)); |
288 |
| - errno = EIO; |
| 281 | + // We need a dummy socket. |
| 282 | + const int fd = socket(AF_INET6, SOCK_STREAM, 0); |
| 283 | + if (fd < 0) { |
| 284 | + LOG_ERR("ListInterfaces: socket(AF_INET, SOCK_DGRAM, 0) failed\n"); |
289 | 285 | return NULL;
|
290 | 286 | }
|
291 | 287 |
|
| 288 | + // Call the ioctls. |
| 289 | + netc_get_if_info_t get_if_info; |
| 290 | + const ssize_t size = ioctl_netc_get_num_ifs(fd, &get_if_info.n_info); |
| 291 | + if (size < 0) { |
| 292 | + LOG_ERR("ListInterfaces: ioctl_netc_get_num_ifs() failed"); |
| 293 | + close(fd); |
| 294 | + return NULL; |
| 295 | + } |
| 296 | + for (uint32_t i = 0; i < get_if_info.n_info; i++) { |
| 297 | + const ssize_t size = |
| 298 | + ioctl_netc_get_if_info_at(fd, &i, &get_if_info.info[i]); |
| 299 | + if (size < 0) { |
| 300 | + LOG_ERR("ListInterfaces: ioctl_netc_get_if_info_at() failed"); |
| 301 | + close(fd); |
| 302 | + return NULL; |
| 303 | + } |
| 304 | + } |
| 305 | + |
292 | 306 | // Process the results.
|
293 | 307 | const int lookup_family = SocketAddress::FromType(type);
|
| 308 | + intptr_t count = 0; |
| 309 | + for (intptr_t i = 0; i < get_if_info.n_info; i++) { |
| 310 | + if (ShouldIncludeIfaAddrs(&get_if_info.info[i], lookup_family)) { |
| 311 | + count++; |
| 312 | + } |
| 313 | + } |
294 | 314 |
|
295 |
| - std::remove_if( |
296 |
| - interfaces.begin(), interfaces.end(), |
297 |
| - [lookup_family](const auto& interface) { |
298 |
| - switch (interface.addr.Which()) { |
299 |
| - case fuchsia::net::IpAddress::Tag::kIpv4: |
300 |
| - return !(lookup_family == AF_UNSPEC || lookup_family == AF_INET); |
301 |
| - case fuchsia::net::IpAddress::Tag::kIpv6: |
302 |
| - return !(lookup_family == AF_UNSPEC || lookup_family == AF_INET6); |
303 |
| - case fuchsia::net::IpAddress::Tag::Invalid: |
304 |
| - return true; |
305 |
| - } |
306 |
| - }); |
307 |
| - |
308 |
| - auto addresses = new AddressList<InterfaceSocketAddress>(interfaces.size()); |
| 315 | + AddressList<InterfaceSocketAddress>* addresses = |
| 316 | + new AddressList<InterfaceSocketAddress>(count); |
309 | 317 | int addresses_idx = 0;
|
310 |
| - for (const auto& interface : interfaces) { |
311 |
| - struct sockaddr_storage addr = {}; |
312 |
| - auto addr_in = reinterpret_cast<struct sockaddr_in*>(&addr); |
313 |
| - auto addr_in6 = reinterpret_cast<struct sockaddr_in6*>(&addr); |
314 |
| - switch (interface.addr.Which()) { |
315 |
| - case fuchsia::net::IpAddress::Tag::kIpv4: |
316 |
| - addr_in->sin_family = AF_INET; |
317 |
| - memmove(&addr_in->sin_addr, interface.addr.ipv4().addr.data(), |
318 |
| - sizeof(addr_in->sin_addr)); |
319 |
| - break; |
320 |
| - case fuchsia::net::IpAddress::Tag::kIpv6: |
321 |
| - addr_in6->sin6_family = AF_INET6; |
322 |
| - memmove(&addr_in6->sin6_addr, interface.addr.ipv6().addr.data(), |
323 |
| - sizeof(addr_in6->sin6_addr)); |
324 |
| - break; |
325 |
| - case fuchsia::net::IpAddress::Tag::Invalid: |
326 |
| - // Should have been filtered out above. |
327 |
| - UNREACHABLE(); |
| 318 | + for (intptr_t i = 0; i < get_if_info.n_info; i++) { |
| 319 | + if (ShouldIncludeIfaAddrs(&get_if_info.info[i], lookup_family)) { |
| 320 | + char* ifa_name = DartUtils::ScopedCopyCString(get_if_info.info[i].name); |
| 321 | + InterfaceSocketAddress* isa = new InterfaceSocketAddress( |
| 322 | + reinterpret_cast<struct sockaddr*>(&get_if_info.info[i].addr), |
| 323 | + ifa_name, if_nametoindex(get_if_info.info[i].name)); |
| 324 | + addresses->SetAt(addresses_idx, isa); |
| 325 | + addresses_idx++; |
328 | 326 | }
|
329 |
| - addresses->SetAt(addresses_idx, |
330 |
| - new InterfaceSocketAddress( |
331 |
| - reinterpret_cast<sockaddr*>(&addr), |
332 |
| - DartUtils::ScopedCopyCString(interface.name.c_str()), |
333 |
| - if_nametoindex(interface.name.c_str()))); |
334 |
| - addresses_idx++; |
335 | 327 | }
|
| 328 | + close(fd); |
336 | 329 | return addresses;
|
337 | 330 | }
|
338 | 331 |
|
|
0 commit comments