1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef IFADDRS_ANDROID_H_included 18 #define IFADDRS_ANDROID_H_included 19 20 #include <arpa/inet.h> 21 #include <cstring> 22 #include <errno.h> 23 #include <net/if.h> 24 #include <netinet/in.h> 25 #include <new> 26 #include <sys/ioctl.h> 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 #include <stdio.h> 30 #include <linux/netlink.h> 31 #include <linux/rtnetlink.h> 32 33 #include "LocalArray.h" 34 #include "ScopedFd.h" 35 36 // Android (bionic) doesn't have getifaddrs(3)/freeifaddrs(3). 37 // We fake it here, so java_net_NetworkInterface.cpp can use that API 38 // with all the non-portable code being in this file. 39 40 // Source-compatible subset of the BSD struct. 41 struct ifaddrs { 42 // Pointer to next struct in list, or NULL at end. 43 ifaddrs* ifa_next; 44 45 // Interface name. 46 char* ifa_name; 47 48 // Interface flags. 49 unsigned int ifa_flags; 50 51 // Interface network address. 52 sockaddr* ifa_addr; 53 54 // Interface netmask. 55 sockaddr* ifa_netmask; 56 57 ifaddrs(ifaddrs* next) 58 : ifa_next(next), ifa_name(NULL), ifa_flags(0), ifa_addr(NULL), ifa_netmask(NULL) 59 { 60 } 61 62 ~ifaddrs() { 63 delete ifa_next; 64 delete[] ifa_name; 65 delete ifa_addr; 66 delete ifa_netmask; 67 } 68 69 // Sadly, we can't keep the interface index for portability with BSD. 70 // We'll have to keep the name instead, and re-query the index when 71 // we need it later. 72 bool setNameAndFlagsByIndex(int interfaceIndex) { 73 // Get the name. 74 char buf[IFNAMSIZ]; 75 char* name = if_indextoname(interfaceIndex, buf); 76 if (name == NULL) { 77 return false; 78 } 79 ifa_name = new char[strlen(name) + 1]; 80 strcpy(ifa_name, name); 81 82 // Get the flags. 83 ScopedFd fd(socket(AF_INET, SOCK_DGRAM, 0)); 84 if (fd.get() == -1) { 85 return false; 86 } 87 ifreq ifr; 88 memset(&ifr, 0, sizeof(ifr)); 89 strcpy(ifr.ifr_name, name); 90 int rc = ioctl(fd.get(), SIOCGIFFLAGS, &ifr); 91 if (rc == -1) { 92 return false; 93 } 94 ifa_flags = ifr.ifr_flags; 95 return true; 96 } 97 98 // Netlink gives us the address family in the header, and the 99 // sockaddr_in or sockaddr_in6 bytes as the payload. We need to 100 // stitch the two bits together into the sockaddr that's part of 101 // our portable interface. 102 void setAddress(int family, void* data, size_t byteCount) { 103 // Set the address proper... 104 sockaddr_storage* ss = new sockaddr_storage; 105 memset(ss, 0, sizeof(*ss)); 106 ifa_addr = reinterpret_cast<sockaddr*>(ss); 107 ss->ss_family = family; 108 uint8_t* dst = sockaddrBytes(family, ss); 109 memcpy(dst, data, byteCount); 110 } 111 112 // Netlink gives us the prefix length as a bit count. We need to turn 113 // that into a BSD-compatible netmask represented by a sockaddr*. 114 void setNetmask(int family, size_t prefixLength) { 115 // ...and work out the netmask from the prefix length. 116 sockaddr_storage* ss = new sockaddr_storage; 117 memset(ss, 0, sizeof(*ss)); 118 ifa_netmask = reinterpret_cast<sockaddr*>(ss); 119 ss->ss_family = family; 120 uint8_t* dst = sockaddrBytes(family, ss); 121 memset(dst, 0xff, prefixLength / 8); 122 if ((prefixLength % 8) != 0) { 123 dst[prefixLength/8] = (0xff << (8 - (prefixLength % 8))); 124 } 125 } 126 127 // Returns a pointer to the first byte in the address data (which is 128 // stored in network byte order). 129 uint8_t* sockaddrBytes(int family, sockaddr_storage* ss) { 130 if (family == AF_INET) { 131 sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss); 132 return reinterpret_cast<uint8_t*>(&ss4->sin_addr); 133 } else if (family == AF_INET6) { 134 sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss); 135 return reinterpret_cast<uint8_t*>(&ss6->sin6_addr); 136 } 137 return NULL; 138 } 139 140 private: 141 // Disallow copy and assignment. 142 ifaddrs(const ifaddrs&); 143 void operator=(const ifaddrs&); 144 }; 145 146 // FIXME: use iovec instead. 147 struct addrReq_struct { 148 nlmsghdr netlinkHeader; 149 ifaddrmsg msg; 150 }; 151 152 inline bool sendNetlinkMessage(int fd, const void* data, size_t byteCount) { 153 ssize_t sentByteCount = TEMP_FAILURE_RETRY(send(fd, data, byteCount, 0)); 154 return (sentByteCount == static_cast<ssize_t>(byteCount)); 155 } 156 157 inline ssize_t recvNetlinkMessage(int fd, char* buf, size_t byteCount) { 158 return TEMP_FAILURE_RETRY(recv(fd, buf, byteCount, 0)); 159 } 160 161 // Source-compatible with the BSD function. 162 inline int getifaddrs(ifaddrs** result) { 163 // Simplify cleanup for callers. 164 *result = NULL; 165 166 // Create a netlink socket. 167 ScopedFd fd(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)); 168 if (fd.get() < 0) { 169 return -1; 170 } 171 172 // Ask for the address information. 173 addrReq_struct addrRequest; 174 memset(&addrRequest, 0, sizeof(addrRequest)); 175 addrRequest.netlinkHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH; 176 addrRequest.netlinkHeader.nlmsg_type = RTM_GETADDR; 177 addrRequest.netlinkHeader.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(addrRequest))); 178 addrRequest.msg.ifa_family = AF_UNSPEC; // All families. 179 addrRequest.msg.ifa_index = 0; // All interfaces. 180 if (!sendNetlinkMessage(fd.get(), &addrRequest, addrRequest.netlinkHeader.nlmsg_len)) { 181 return -1; 182 } 183 184 // Read the responses. 185 LocalArray<0> buf(65536); // We don't necessarily have std::vector. 186 ssize_t bytesRead; 187 while ((bytesRead = recvNetlinkMessage(fd.get(), &buf[0], buf.size())) > 0) { 188 nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(&buf[0]); 189 for (; NLMSG_OK(hdr, (size_t)bytesRead); hdr = NLMSG_NEXT(hdr, bytesRead)) { 190 switch (hdr->nlmsg_type) { 191 case NLMSG_DONE: 192 return 0; 193 case NLMSG_ERROR: 194 return -1; 195 case RTM_NEWADDR: 196 { 197 ifaddrmsg* address = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr)); 198 rtattr* rta = IFA_RTA(address); 199 size_t ifaPayloadLength = IFA_PAYLOAD(hdr); 200 while (RTA_OK(rta, ifaPayloadLength)) { 201 if (rta->rta_type == IFA_LOCAL) { 202 int family = address->ifa_family; 203 if (family == AF_INET || family == AF_INET6) { 204 *result = new ifaddrs(*result); 205 if (!(*result)->setNameAndFlagsByIndex(address->ifa_index)) { 206 return -1; 207 } 208 (*result)->setAddress(family, RTA_DATA(rta), RTA_PAYLOAD(rta)); 209 (*result)->setNetmask(family, address->ifa_prefixlen); 210 } 211 } 212 rta = RTA_NEXT(rta, ifaPayloadLength); 213 } 214 } 215 break; 216 } 217 } 218 } 219 // We only get here if recv fails before we see a NLMSG_DONE. 220 return -1; 221 } 222 223 // Source-compatible with the BSD function. 224 inline void freeifaddrs(ifaddrs* addresses) { 225 delete addresses; 226 } 227 228 #endif // IFADDRS_ANDROID_H_included 229