5#if defined(ANDROID) && __ANDROID_API__ < 24
10#include <linux/netlink.h>
11#include <linux/rtnetlink.h>
13#include <netinet/in.h>
17#include <sys/socket.h>
19#include <sys/utsname.h>
28const int kMaxReadSize = 2048;
30static bool SetIfName(
struct ifaddrs* ifaddr,
int interface) {
31 char buf[IFNAMSIZ] = {0};
32 char*
name = if_indextoname(interface, buf);
33 if (
name ==
nullptr) {
36 ifaddr->ifa_name =
new char[strlen(
name) + 1];
37 strncpy(ifaddr->ifa_name,
name, strlen(
name) + 1);
41static void SetFlags(
struct ifaddrs* ifaddr,
int flag) {
42 ifaddr->ifa_flags =
flag;
45static void SetAddresses(
struct ifaddrs* ifaddr,
50 if (family == AF_INET6) {
51 sockaddr_in6* socketaddr =
new sockaddr_in6;
52 socketaddr->sin6_family = AF_INET6;
53 socketaddr->sin6_scope_id = index;
54 memmove(&socketaddr->sin6_addr,
data,
len);
55 ifaddr->ifa_addr =
reinterpret_cast<sockaddr*
>(socketaddr);
59 sockaddr_in* socketaddr =
new sockaddr_in;
60 socketaddr->sin_family = AF_INET;
61 memmove(&socketaddr->sin_addr,
data,
len);
62 ifaddr->ifa_addr =
reinterpret_cast<sockaddr*
>(socketaddr);
65static void SetNetmask(
struct ifaddrs* ifaddr,
int family) {
66 if (family == AF_INET6) {
67 sockaddr_in6* mask =
new sockaddr_in6;
68 mask->sin6_family = AF_INET6;
69 memset(&mask->sin6_addr, 0,
sizeof(mask->sin6_addr));
70 ifaddr->ifa_netmask =
reinterpret_cast<sockaddr*
>(mask);
74 sockaddr_in* mask =
new sockaddr_in;
75 mask->sin_family = AF_INET;
76 memset(&mask->sin_addr, 0,
sizeof(mask->sin_addr));
77 ifaddr->ifa_netmask =
reinterpret_cast<sockaddr*
>(mask);
80static bool SetIfAddrsFromAddrMsg(
struct ifaddrs* ifaddr,
85 SetAddresses(ifaddr, msg->ifa_family, msg->ifa_index, bytes,
len);
86 SetNetmask(ifaddr, msg->ifa_family);
87 SetFlags(ifaddr, msg->ifa_flags);
88 return SetIfName(ifaddr, msg->ifa_index);
91static bool SetIfAddrsFromInfoMsg(
struct ifaddrs* ifaddr,
96 SetAddresses(ifaddr, ifi->ifi_family, ifi->ifi_index, bytes,
len);
97 SetNetmask(ifaddr, ifi->ifi_family);
98 SetFlags(ifaddr, ifi->ifi_flags);
99 return SetIfName(ifaddr, ifi->ifi_index);
102static int SendRequest() {
103 int file_descriptor =
105 if (file_descriptor < 0) {
110 header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
111 header.nlmsg_type = RTM_GETADDR;
112 header.nlmsg_len = NLMSG_LENGTH(
sizeof(ifaddrmsg));
115 if (
static_cast<size_t>(num) !=
header.nlmsg_len) {
119 return file_descriptor;
122static int FailAndExit(
int fd, ifaddrs*
head) {
128int getifaddrs(
struct ifaddrs**
result) {
129 int file_descriptor = SendRequest();
130 if (file_descriptor < 0) {
133 struct ifaddrs*
head =
nullptr;
134 struct ifaddrs* cur =
nullptr;
135 char buf[kMaxReadSize];
140 if (amount_read <= 0) {
143 nlmsghdr*
header =
reinterpret_cast<nlmsghdr*
>(&buf[0]);
144 size_t header_size =
static_cast<size_t>(amount_read);
145 for (; NLMSG_OK(
header, header_size);
147 switch (
header->nlmsg_type) {
149 ifaddrmsg* address_msg =
150 reinterpret_cast<ifaddrmsg*
>(NLMSG_DATA(
header));
151 ssize_t payload_len = IFA_PAYLOAD(
header);
152 for (rtattr* rta = IFA_RTA(address_msg); RTA_OK(rta, payload_len);
153 rta = RTA_NEXT(rta, payload_len)) {
154 if (rta->rta_type != IFA_ADDRESS) {
157 int family = address_msg->ifa_family;
158 if (family != AF_INET && family != AF_INET6) {
161 ifaddrs*
next =
new ifaddrs;
163 if (cur !=
nullptr) {
164 cur->ifa_next =
next;
168 if (!SetIfAddrsFromAddrMsg(
next, address_msg, RTA_DATA(rta),
169 RTA_PAYLOAD(rta),
header)) {
170 return FailAndExit(file_descriptor,
head);
177 ifinfomsg* ifi =
reinterpret_cast<ifinfomsg*
>(NLMSG_DATA(
header));
178 ssize_t payload_len = IFLA_PAYLOAD(
header);
179 for (rtattr* rta = IFLA_RTA(ifi); RTA_OK(rta, payload_len);
180 rta = RTA_NEXT(rta, payload_len)) {
181 if (rta->rta_type != IFA_ADDRESS) {
184 int family = ifi->ifi_family;
185 if (family != AF_INET && family != AF_INET6) {
188 ifaddrs*
next =
new ifaddrs;
190 if (cur !=
nullptr) {
191 cur->ifa_next =
next;
195 if (!SetIfAddrsFromInfoMsg(
next, ifi, RTA_DATA(rta),
196 RTA_PAYLOAD(rta),
header)) {
197 return FailAndExit(file_descriptor,
head);
208 return FailAndExit(file_descriptor,
head);
212 return FailAndExit(file_descriptor,
head);
215void freeifaddrs(
struct ifaddrs* addrs) {
217 struct ifaddrs* previous =
nullptr;
218 while (addrs !=
nullptr) {
219 delete[] addrs->ifa_name;
220 delete addrs->ifa_addr;
221 delete addrs->ifa_netmask;
223 addrs = addrs->ifa_next;
static float next(float f)
static void SaveErrorAndClose(intptr_t fd)
FlutterSemanticsFlag flag
static int8_t data[kExtLength]
#define NO_RETRY_EXPECTED(expression)
#define TEMP_FAILURE_RETRY(expression)
static const char header[]