1// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "platform/globals.h"
6#if defined(HOST_OS_ANDROID)
7
8#include "bin/socket_base.h"
9
10#include <errno.h>
11#include <ifaddrs.h>
12#include <net/if.h>
13#include <netinet/tcp.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <sys/stat.h>
18#include <unistd.h>
19
20#include "bin/fdutils.h"
21#include "bin/file.h"
22#include "bin/ifaddrs-android.h"
23#include "bin/socket_base_android.h"
24#include "platform/signal_blocker.h"
25
26namespace dart {
27namespace bin {
28
29SocketAddress::SocketAddress(struct sockaddr* sa, bool unnamed_unix_socket) {
30 if (unnamed_unix_socket) {
31 // This is an unnamed unix domain socket.
32 as_string_[0] = 0;
33 } else if (sa->sa_family == AF_UNIX) {
34 struct sockaddr_un* un = ((struct sockaddr_un*)sa);
35 memmove(as_string_, un->sun_path, sizeof(un->sun_path));
36 } else {
37 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
38 if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa),
39 as_string_, INET6_ADDRSTRLEN)) {
40 as_string_[0] = 0;
41 }
42 }
43 socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa));
44 memmove(reinterpret_cast<void*>(&addr_), sa, salen);
45}
46
47bool SocketBase::Initialize() {
48 // Nothing to do on Android.
49 return true;
50}
51
52bool SocketBase::FormatNumericAddress(const RawAddr& addr,
53 char* address,
54 int len) {
55 socklen_t salen = SocketAddress::GetAddrLength(addr);
56 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL,
57 0, NI_NUMERICHOST)) == 0);
58}
59
60bool SocketBase::IsBindError(intptr_t error_number) {
61 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL ||
62 error_number == EINVAL;
63}
64
65intptr_t SocketBase::Available(intptr_t fd) {
66 return FDUtils::AvailableBytes(fd);
67}
68
69intptr_t SocketBase::Read(intptr_t fd,
70 void* buffer,
71 intptr_t num_bytes,
72 SocketOpKind sync) {
73 ASSERT(fd >= 0);
74 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
75 ASSERT(EAGAIN == EWOULDBLOCK);
76 if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
77 // If the read would block we need to retry and therefore return 0
78 // as the number of bytes written.
79 read_bytes = 0;
80 }
81 return read_bytes;
82}
83
84intptr_t SocketBase::RecvFrom(intptr_t fd,
85 void* buffer,
86 intptr_t num_bytes,
87 RawAddr* addr,
88 SocketOpKind sync) {
89 ASSERT(fd >= 0);
90 socklen_t addr_len = sizeof(addr->ss);
91 ssize_t read_bytes = TEMP_FAILURE_RETRY(
92 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
93 if ((sync == kAsync) && (read_bytes == -1) && (errno == EWOULDBLOCK)) {
94 // If the read would block we need to retry and therefore return 0
95 // as the number of bytes written.
96 read_bytes = 0;
97 }
98 return read_bytes;
99}
100
101bool SocketBase::AvailableDatagram(intptr_t fd,
102 void* buffer,
103 intptr_t num_bytes) {
104 ASSERT(fd >= 0);
105 ssize_t read_bytes =
106 TEMP_FAILURE_RETRY(recvfrom(fd, buffer, num_bytes, MSG_PEEK, NULL, NULL));
107 return read_bytes >= 0;
108}
109
110intptr_t SocketBase::Write(intptr_t fd,
111 const void* buffer,
112 intptr_t num_bytes,
113 SocketOpKind sync) {
114 ASSERT(fd >= 0);
115 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
116 ASSERT(EAGAIN == EWOULDBLOCK);
117 if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
118 // If the would block we need to retry and therefore return 0 as
119 // the number of bytes written.
120 written_bytes = 0;
121 }
122 return written_bytes;
123}
124
125intptr_t SocketBase::SendTo(intptr_t fd,
126 const void* buffer,
127 intptr_t num_bytes,
128 const RawAddr& addr,
129 SocketOpKind sync) {
130 ASSERT(fd >= 0);
131 ssize_t written_bytes =
132 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr,
133 SocketAddress::GetAddrLength(addr)));
134 ASSERT(EAGAIN == EWOULDBLOCK);
135 if ((sync == kAsync) && (written_bytes == -1) && (errno == EWOULDBLOCK)) {
136 // If the would block we need to retry and therefore return 0 as
137 // the number of bytes written.
138 written_bytes = 0;
139 }
140 return written_bytes;
141}
142
143intptr_t SocketBase::GetPort(intptr_t fd) {
144 ASSERT(fd >= 0);
145 RawAddr raw;
146 socklen_t size = sizeof(raw);
147 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
148 return 0;
149 }
150 return SocketAddress::GetAddrPort(raw);
151}
152
153SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) {
154 ASSERT(fd >= 0);
155 RawAddr raw;
156 socklen_t size = sizeof(raw);
157 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) {
158 return NULL;
159 }
160 // sockaddr_un contains sa_family_t sun_familty and char[] sun_path.
161 // If size is the size of sa_familty_t, this is an unnamed socket and
162 // sun_path contains garbage.
163 if (size == sizeof(sa_family_t)) {
164 *port = 0;
165 return new SocketAddress(&raw.addr, true);
166 }
167 *port = SocketAddress::GetAddrPort(raw);
168 return new SocketAddress(&raw.addr);
169}
170
171void SocketBase::GetError(intptr_t fd, OSError* os_error) {
172 int errorNumber;
173 socklen_t len = sizeof(errorNumber);
174 getsockopt(fd, SOL_SOCKET, SO_ERROR, reinterpret_cast<void*>(&errorNumber),
175 &len);
176 os_error->SetCodeAndMessage(OSError::kSystem, errorNumber);
177}
178
179int SocketBase::GetType(intptr_t fd) {
180 struct stat buf;
181 int result = fstat(fd, &buf);
182 if (result == -1) {
183 return -1;
184 }
185 if (S_ISCHR(buf.st_mode)) {
186 return File::kTerminal;
187 }
188 if (S_ISFIFO(buf.st_mode)) {
189 return File::kPipe;
190 }
191 if (S_ISREG(buf.st_mode)) {
192 return File::kFile;
193 }
194 return File::kOther;
195}
196
197intptr_t SocketBase::GetStdioHandle(intptr_t num) {
198 return num;
199}
200
201AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
202 int type,
203 OSError** os_error) {
204 // Perform a name lookup for a host name.
205 struct addrinfo hints;
206 memset(&hints, 0, sizeof(hints));
207 hints.ai_family = SocketAddress::FromType(type);
208 hints.ai_socktype = SOCK_STREAM;
209 hints.ai_flags = AI_ADDRCONFIG;
210 hints.ai_protocol = IPPROTO_TCP;
211 struct addrinfo* info = NULL;
212 int status = getaddrinfo(host, 0, &hints, &info);
213 if (status != 0) {
214 // We failed, try without AI_ADDRCONFIG. This can happen when looking up
215 // e.g. '::1', when there are no IPv6 addresses.
216 hints.ai_flags = 0;
217 status = getaddrinfo(host, 0, &hints, &info);
218 if (status != 0) {
219 ASSERT(*os_error == NULL);
220 *os_error =
221 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
222 return NULL;
223 }
224 }
225 intptr_t count = 0;
226 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
227 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
228 count++;
229 }
230 }
231 intptr_t i = 0;
232 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
233 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
234 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
235 addresses->SetAt(i, new SocketAddress(c->ai_addr));
236 i++;
237 }
238 }
239 freeaddrinfo(info);
240 return addresses;
241}
242
243bool SocketBase::ReverseLookup(const RawAddr& addr,
244 char* host,
245 intptr_t host_len,
246 OSError** os_error) {
247 ASSERT(host_len >= NI_MAXHOST);
248 int status = NO_RETRY_EXPECTED(
249 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host,
250 host_len, NULL, 0, NI_NAMEREQD));
251 if (status != 0) {
252 ASSERT(*os_error == NULL);
253 *os_error =
254 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
255 return false;
256 }
257 return true;
258}
259
260bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) {
261 int result;
262 if (type == SocketAddress::TYPE_IPV4) {
263 result = inet_pton(AF_INET, address, &addr->in.sin_addr);
264 } else {
265 ASSERT(type == SocketAddress::TYPE_IPV6);
266 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
267 }
268 return (result == 1);
269}
270
271bool SocketBase::RawAddrToString(RawAddr* addr, char* str) {
272 if (addr->addr.sa_family == AF_INET) {
273 return inet_ntop(AF_INET, &addr->in.sin_addr, str, INET_ADDRSTRLEN) != NULL;
274 } else {
275 ASSERT(addr->addr.sa_family == AF_INET6);
276 return inet_ntop(AF_INET6, &addr->in6.sin6_addr, str, INET6_ADDRSTRLEN) !=
277 NULL;
278 }
279}
280
281static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
282 if (ifa->ifa_addr == NULL) {
283 // OpenVPN's virtual device tun0.
284 return false;
285 }
286 int family = ifa->ifa_addr->sa_family;
287 return ((lookup_family == family) ||
288 (((lookup_family == AF_UNSPEC) &&
289 ((family == AF_INET) || (family == AF_INET6)))));
290}
291
292bool SocketBase::ListInterfacesSupported() {
293 return true;
294}
295
296AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
297 int type,
298 OSError** os_error) {
299 struct ifaddrs* ifaddr;
300
301 int status = NO_RETRY_EXPECTED(getifaddrs(&ifaddr));
302 if (status != 0) {
303 ASSERT(*os_error == NULL);
304 *os_error =
305 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
306 return NULL;
307 }
308
309 int lookup_family = SocketAddress::FromType(type);
310
311 intptr_t count = 0;
312 for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
313 if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
314 count++;
315 }
316 }
317
318 AddressList<InterfaceSocketAddress>* addresses =
319 new AddressList<InterfaceSocketAddress>(count);
320 int i = 0;
321 for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
322 if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
323 char* ifa_name = DartUtils::ScopedCopyCString(ifa->ifa_name);
324 addresses->SetAt(
325 i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name,
326 if_nametoindex(ifa->ifa_name)));
327 i++;
328 }
329 }
330 freeifaddrs(ifaddr);
331 return addresses;
332}
333
334void SocketBase::Close(intptr_t fd) {
335 ASSERT(fd >= 0);
336 close(fd);
337}
338
339bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) {
340 int on;
341 socklen_t len = sizeof(on);
342 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
343 reinterpret_cast<void*>(&on), &len));
344 if (err == 0) {
345 *enabled = (on == 1);
346 }
347 return (err == 0);
348}
349
350bool SocketBase::SetNoDelay(intptr_t fd, bool enabled) {
351 int on = enabled ? 1 : 0;
352 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
353 reinterpret_cast<char*>(&on),
354 sizeof(on))) == 0;
355}
356
357bool SocketBase::GetMulticastLoop(intptr_t fd,
358 intptr_t protocol,
359 bool* enabled) {
360 uint8_t on;
361 socklen_t len = sizeof(on);
362 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
363 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
364 : IPV6_MULTICAST_LOOP;
365 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
366 reinterpret_cast<char*>(&on), &len)) == 0) {
367 *enabled = (on == 1);
368 return true;
369 }
370 return false;
371}
372
373bool SocketBase::SetMulticastLoop(intptr_t fd,
374 intptr_t protocol,
375 bool enabled) {
376 int on = enabled ? 1 : 0;
377 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
378 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
379 : IPV6_MULTICAST_LOOP;
380 return NO_RETRY_EXPECTED(setsockopt(
381 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) ==
382 0;
383}
384
385bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
386 uint8_t v;
387 socklen_t len = sizeof(v);
388 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
389 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
390 : IPV6_MULTICAST_HOPS;
391 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
392 reinterpret_cast<char*>(&v), &len)) == 0) {
393 *value = v;
394 return true;
395 }
396 return false;
397}
398
399bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
400 int v = value;
401 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
402 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
403 : IPV6_MULTICAST_HOPS;
404 return NO_RETRY_EXPECTED(setsockopt(
405 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0;
406}
407
408bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) {
409 int on;
410 socklen_t len = sizeof(on);
411 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST,
412 reinterpret_cast<char*>(&on), &len));
413 if (err == 0) {
414 *enabled = (on == 1);
415 }
416 return (err == 0);
417}
418
419bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) {
420 int on = enabled ? 1 : 0;
421 return NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
422 reinterpret_cast<char*>(&on),
423 sizeof(on))) == 0;
424}
425
426bool SocketBase::SetOption(intptr_t fd,
427 int level,
428 int option,
429 const char* data,
430 int length) {
431 return NO_RETRY_EXPECTED(setsockopt(fd, level, option, data, length)) == 0;
432}
433
434bool SocketBase::GetOption(intptr_t fd,
435 int level,
436 int option,
437 char* data,
438 unsigned int* length) {
439 socklen_t optlen = static_cast<socklen_t>(*length);
440 auto result = NO_RETRY_EXPECTED(getsockopt(fd, level, option, data, &optlen));
441 *length = static_cast<unsigned int>(optlen);
442 return result == 0;
443}
444
445bool SocketBase::JoinMulticast(intptr_t fd,
446 const RawAddr& addr,
447 const RawAddr&,
448 int interfaceIndex) {
449 int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
450 struct group_req mreq;
451 mreq.gr_interface = interfaceIndex;
452 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
453 return NO_RETRY_EXPECTED(
454 setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
455}
456
457bool SocketBase::LeaveMulticast(intptr_t fd,
458 const RawAddr& addr,
459 const RawAddr&,
460 int interfaceIndex) {
461 int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
462 struct group_req mreq;
463 mreq.gr_interface = interfaceIndex;
464 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
465 return NO_RETRY_EXPECTED(setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq,
466 sizeof(mreq))) == 0;
467}
468
469} // namespace bin
470} // namespace dart
471
472#endif // defined(HOST_OS_ANDROID)
473