InterfaceController.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. * Copyright (C) 2012 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. #include <dirent.h>
  17. #include <errno.h>
  18. #include <malloc.h>
  19. #include <net/if.h>
  20. #include <net/if_arp.h>
  21. #include <sys/socket.h>
  22. #include <functional>
  23. #define LOG_TAG "InterfaceController"
  24. #include <android-base/file.h>
  25. #include <android-base/properties.h>
  26. #include <android-base/stringprintf.h>
  27. #include <android-base/strings.h>
  28. #include <linux/if_ether.h>
  29. #include <log/log.h>
  30. #include <logwrap/logwrap.h>
  31. #include <netutils/ifc.h>
  32. #include <android/net/INetd.h>
  33. #include <netdutils/Misc.h>
  34. #include <netdutils/Slice.h>
  35. #include <netdutils/Syscalls.h>
  36. #include "InterfaceController.h"
  37. #include "RouteController.h"
  38. using android::base::ReadFileToString;
  39. using android::base::StringPrintf;
  40. using android::base::Trim;
  41. using android::base::WriteStringToFile;
  42. using android::net::INetd;
  43. using android::net::RouteController;
  44. using android::netdutils::isOk;
  45. using android::netdutils::makeSlice;
  46. using android::netdutils::sSyscalls;
  47. using android::netdutils::Status;
  48. using android::netdutils::statusFromErrno;
  49. using android::netdutils::StatusOr;
  50. using android::netdutils::toString;
  51. using android::netdutils::status::ok;
  52. #define RETURN_STATUS_IF_IFCERROR(exp) \
  53. do { \
  54. if ((exp) == -1) { \
  55. return statusFromErrno(errno, "Failed to add addr"); \
  56. } \
  57. } while (0);
  58. namespace {
  59. const char ipv4_proc_path[] = "/proc/sys/net/ipv4/conf";
  60. const char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
  61. const char ipv4_neigh_conf_dir[] = "/proc/sys/net/ipv4/neigh";
  62. const char ipv6_neigh_conf_dir[] = "/proc/sys/net/ipv6/neigh";
  63. const char proc_net_path[] = "/proc/sys/net";
  64. const char sys_net_path[] = "/sys/class/net";
  65. constexpr int kRouteInfoMinPrefixLen = 48;
  66. // RFC 7421 prefix length.
  67. constexpr int kRouteInfoMaxPrefixLen = 64;
  68. // Property used to persist RFC 7217 stable secret. Protected by SELinux policy.
  69. const char kStableSecretProperty[] = "persist.netd.stable_secret";
  70. // RFC 7217 stable secret on linux is formatted as an IPv6 address.
  71. // This function uses 128 bits of high quality entropy to generate an
  72. // address for this purpose. This function should be not be called
  73. // frequently.
  74. StatusOr<std::string> randomIPv6Address() {
  75. in6_addr addr = {};
  76. const auto& sys = sSyscalls.get();
  77. ASSIGN_OR_RETURN(auto fd, sys.open("/dev/random", O_RDONLY));
  78. RETURN_IF_NOT_OK(sys.read(fd, makeSlice(addr)));
  79. return toString(addr);
  80. }
  81. inline bool isNormalPathComponent(const char *component) {
  82. return (strcmp(component, ".") != 0) &&
  83. (strcmp(component, "..") != 0) &&
  84. (strchr(component, '/') == nullptr);
  85. }
  86. inline bool isAddressFamilyPathComponent(const char *component) {
  87. return strcmp(component, "ipv4") == 0 || strcmp(component, "ipv6") == 0;
  88. }
  89. inline bool isInterfaceName(const char *name) {
  90. return isNormalPathComponent(name) &&
  91. (strcmp(name, "default") != 0) &&
  92. (strcmp(name, "all") != 0);
  93. }
  94. int writeValueToPath(
  95. const char* dirname, const char* subdirname, const char* basename,
  96. const char* value) {
  97. std::string path(StringPrintf("%s/%s/%s", dirname, subdirname, basename));
  98. return WriteStringToFile(value, path) ? 0 : -EREMOTEIO;
  99. }
  100. // Run @fn on each interface as well as 'default' in the path @dirname.
  101. void forEachInterface(
  102. const std::string& dirname,
  103. const std::function<void(const std::string& path, const std::string& iface)>& fn) {
  104. // Run on default, which controls the behavior of any interfaces that are created in the future.
  105. fn(dirname, "default");
  106. DIR* dir = opendir(dirname.c_str());
  107. if (!dir) {
  108. ALOGE("Can't list %s: %s", dirname.c_str(), strerror(errno));
  109. return;
  110. }
  111. while (true) {
  112. const dirent *ent = readdir(dir);
  113. if (!ent) {
  114. break;
  115. }
  116. if ((ent->d_type != DT_DIR) || !isInterfaceName(ent->d_name)) {
  117. continue;
  118. }
  119. fn(dirname, ent->d_name);
  120. }
  121. closedir(dir);
  122. }
  123. void setOnAllInterfaces(const char* dirname, const char* basename, const char* value) {
  124. auto fn = [basename, value](const std::string& path, const std::string& iface) {
  125. writeValueToPath(path.c_str(), iface.c_str(), basename, value);
  126. };
  127. forEachInterface(dirname, fn);
  128. }
  129. void setIPv6UseOutgoingInterfaceAddrsOnly(const char *value) {
  130. setOnAllInterfaces(ipv6_proc_path, "use_oif_addrs_only", value);
  131. }
  132. std::string getParameterPathname(
  133. const char *family, const char *which, const char *interface, const char *parameter) {
  134. if (!isAddressFamilyPathComponent(family)) {
  135. errno = EAFNOSUPPORT;
  136. return "";
  137. } else if (!isNormalPathComponent(which) ||
  138. !isInterfaceName(interface) ||
  139. !isNormalPathComponent(parameter)) {
  140. errno = EINVAL;
  141. return "";
  142. }
  143. return StringPrintf("%s/%s/%s/%s/%s", proc_net_path, family, which, interface, parameter);
  144. }
  145. void setAcceptIPv6RIO(int min, int max) {
  146. auto fn = [min, max](const std::string& prefix, const std::string& iface) {
  147. int rv = writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_min_plen",
  148. std::to_string(min).c_str());
  149. if (rv != 0) {
  150. // Only update max_plen if the write to min_plen succeeded. This ordering will prevent
  151. // RIOs from being accepted unless both min and max are written successfully.
  152. return;
  153. }
  154. writeValueToPath(prefix.c_str(), iface.c_str(), "accept_ra_rt_info_max_plen",
  155. std::to_string(max).c_str());
  156. };
  157. forEachInterface(ipv6_proc_path, fn);
  158. }
  159. // Ideally this function would return StatusOr<std::string>, however
  160. // there is no safe value for dflt that will always differ from the
  161. // stored property. Bugs code could conceivably end up persisting the
  162. // reserved value resulting in surprising behavior.
  163. std::string getProperty(const std::string& key, const std::string& dflt) {
  164. return android::base::GetProperty(key, dflt);
  165. };
  166. Status setProperty(const std::string& key, const std::string& val) {
  167. // SetProperty does not dependably set errno to a meaningful value. Use our own error code so
  168. // callers don't get confused.
  169. return android::base::SetProperty(key, val)
  170. ? ok
  171. : statusFromErrno(EREMOTEIO, "SetProperty failed, see libc logs");
  172. };
  173. } // namespace
  174. namespace android {
  175. namespace net {
  176. std::mutex InterfaceController::mutex;
  177. android::netdutils::Status InterfaceController::enableStablePrivacyAddresses(
  178. const std::string& iface,
  179. const GetPropertyFn& getProperty,
  180. const SetPropertyFn& setProperty) {
  181. const auto& sys = sSyscalls.get();
  182. const std::string procTarget = std::string(ipv6_proc_path) + "/" + iface + "/stable_secret";
  183. auto procFd = sys.open(procTarget, O_CLOEXEC | O_WRONLY);
  184. // Devices with old kernels (typically < 4.4) don't support
  185. // RFC 7217 stable privacy addresses.
  186. if (equalToErrno(procFd, ENOENT)) {
  187. return statusFromErrno(EOPNOTSUPP,
  188. "Failed to open stable_secret. Assuming unsupported kernel version");
  189. }
  190. // If stable_secret exists but we can't open it, something strange is going on.
  191. RETURN_IF_NOT_OK(procFd);
  192. const char kUninitialized[] = "uninitialized";
  193. const auto oldSecret = getProperty(kStableSecretProperty, kUninitialized);
  194. std::string secret = oldSecret;
  195. // Generate a new secret if no persistent property existed.
  196. if (oldSecret == kUninitialized) {
  197. ASSIGN_OR_RETURN(secret, randomIPv6Address());
  198. }
  199. // Ask the OS to generate SLAAC addresses on iface using secret.
  200. RETURN_IF_NOT_OK(sys.write(procFd.value(), makeSlice(secret)));
  201. // Don't persist an existing secret.
  202. if (oldSecret != kUninitialized) {
  203. return ok;
  204. }
  205. return setProperty(kStableSecretProperty, secret);
  206. }
  207. void InterfaceController::initializeAll() {
  208. // Initial IPv6 settings.
  209. // By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
  210. // This causes RAs to work or not work based on whether forwarding is on, and causes routes
  211. // learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
  212. // by always setting accept_ra to 2.
  213. setAcceptRA("2");
  214. // Accept RIOs with prefix length in the closed interval [48, 64].
  215. setAcceptIPv6RIO(kRouteInfoMinPrefixLen, kRouteInfoMaxPrefixLen);
  216. setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);
  217. // Enable optimistic DAD for IPv6 addresses on all interfaces.
  218. setIPv6OptimisticMode("1");
  219. // Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
  220. setBaseReachableTimeMs(15 * 1000);
  221. // When sending traffic via a given interface use only addresses configured
  222. // on that interface as possible source addresses.
  223. setIPv6UseOutgoingInterfaceAddrsOnly("1");
  224. // Ensure that ICMP redirects are rejected globally on all interfaces.
  225. disableIcmpRedirects();
  226. }
  227. int InterfaceController::setEnableIPv6(const char *interface, const int on) {
  228. if (!isIfaceName(interface)) {
  229. return -ENOENT;
  230. }
  231. // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
  232. // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
  233. // addresses and routes and disables IPv6 on the interface.
  234. const char *disable_ipv6 = on ? "0" : "1";
  235. return writeValueToPath(ipv6_proc_path, interface, "disable_ipv6", disable_ipv6);
  236. }
  237. // Changes to addrGenMode will not fully take effect until the next
  238. // time disable_ipv6 transitions from 1 to 0.
  239. Status InterfaceController::setIPv6AddrGenMode(const std::string& interface, int mode) {
  240. if (!isIfaceName(interface)) {
  241. return statusFromErrno(ENOENT, "invalid iface name: " + interface);
  242. }
  243. switch (mode) {
  244. case INetd::IPV6_ADDR_GEN_MODE_EUI64:
  245. // Ignore return value. If /proc/.../stable_secret is
  246. // missing we're probably in EUI64 mode already.
  247. writeValueToPath(ipv6_proc_path, interface.c_str(), "stable_secret", "");
  248. break;
  249. case INetd::IPV6_ADDR_GEN_MODE_STABLE_PRIVACY: {
  250. return enableStablePrivacyAddresses(interface, getProperty, setProperty);
  251. }
  252. case INetd::IPV6_ADDR_GEN_MODE_NONE:
  253. case INetd::IPV6_ADDR_GEN_MODE_RANDOM:
  254. default:
  255. return statusFromErrno(EOPNOTSUPP, "unsupported addrGenMode");
  256. }
  257. return ok;
  258. }
  259. int InterfaceController::setAcceptIPv6Ra(const char *interface, const int on) {
  260. if (!isIfaceName(interface)) {
  261. errno = ENOENT;
  262. return -1;
  263. }
  264. // Because forwarding can be enabled even when tethering is off, we always
  265. // use mode "2" (accept RAs, even if forwarding is enabled).
  266. const char *accept_ra = on ? "2" : "0";
  267. return writeValueToPath(ipv6_proc_path, interface, "accept_ra", accept_ra);
  268. }
  269. int InterfaceController::setAcceptIPv6Dad(const char *interface, const int on) {
  270. if (!isIfaceName(interface)) {
  271. errno = ENOENT;
  272. return -1;
  273. }
  274. const char *accept_dad = on ? "1" : "0";
  275. return writeValueToPath(ipv6_proc_path, interface, "accept_dad", accept_dad);
  276. }
  277. int InterfaceController::setIPv6DadTransmits(const char *interface, const char *value) {
  278. if (!isIfaceName(interface)) {
  279. errno = ENOENT;
  280. return -1;
  281. }
  282. return writeValueToPath(ipv6_proc_path, interface, "dad_transmits", value);
  283. }
  284. int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
  285. if (!isIfaceName(interface)) {
  286. errno = ENOENT;
  287. return -errno;
  288. }
  289. // 0: disable IPv6 privacy addresses
  290. // 2: enable IPv6 privacy addresses and prefer them over non-privacy ones.
  291. return writeValueToPath(ipv6_proc_path, interface, "use_tempaddr", on ? "2" : "0");
  292. }
  293. void InterfaceController::setAcceptRA(const char *value) {
  294. setOnAllInterfaces(ipv6_proc_path, "accept_ra", value);
  295. }
  296. // |tableOrOffset| is interpreted as:
  297. // If == 0: default. Routes go into RT6_TABLE_MAIN.
  298. // If > 0: user set. Routes go into the specified table.
  299. // If < 0: automatic. The absolute value is intepreted as an offset and added to the interface
  300. // ID to get the table. If it's set to -1000, routes from interface ID 5 will go into
  301. // table 1005, etc.
  302. void InterfaceController::setAcceptRARouteTable(int tableOrOffset) {
  303. std::string value(StringPrintf("%d", tableOrOffset));
  304. setOnAllInterfaces(ipv6_proc_path, "accept_ra_rt_table", value.c_str());
  305. }
  306. int InterfaceController::setMtu(const char *interface, const char *mtu)
  307. {
  308. if (!isIfaceName(interface)) {
  309. errno = ENOENT;
  310. return -errno;
  311. }
  312. return writeValueToPath(sys_net_path, interface, "mtu", mtu);
  313. }
  314. int InterfaceController::addAddress(const char *interface,
  315. const char *addrString, int prefixLength) {
  316. return ifc_add_address(interface, addrString, prefixLength);
  317. }
  318. int InterfaceController::delAddress(const char *interface,
  319. const char *addrString, int prefixLength) {
  320. return ifc_del_address(interface, addrString, prefixLength);
  321. }
  322. int InterfaceController::disableIcmpRedirects() {
  323. int rv = 0;
  324. rv |= writeValueToPath(ipv4_proc_path, "all", "accept_redirects", "0");
  325. rv |= writeValueToPath(ipv6_proc_path, "all", "accept_redirects", "0");
  326. setOnAllInterfaces(ipv4_proc_path, "accept_redirects", "0");
  327. setOnAllInterfaces(ipv6_proc_path, "accept_redirects", "0");
  328. return rv;
  329. }
  330. int InterfaceController::getParameter(
  331. const char *family, const char *which, const char *interface, const char *parameter,
  332. std::string *value) {
  333. const std::string path(getParameterPathname(family, which, interface, parameter));
  334. if (path.empty()) {
  335. return -errno;
  336. }
  337. if (ReadFileToString(path, value)) {
  338. *value = Trim(*value);
  339. return 0;
  340. }
  341. return -errno;
  342. }
  343. int InterfaceController::setParameter(
  344. const char *family, const char *which, const char *interface, const char *parameter,
  345. const char *value) {
  346. const std::string path(getParameterPathname(family, which, interface, parameter));
  347. if (path.empty()) {
  348. return -errno;
  349. }
  350. return WriteStringToFile(value, path) ? 0 : -errno;
  351. }
  352. void InterfaceController::setBaseReachableTimeMs(unsigned int millis) {
  353. std::string value(StringPrintf("%u", millis));
  354. setOnAllInterfaces(ipv4_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
  355. setOnAllInterfaces(ipv6_neigh_conf_dir, "base_reachable_time_ms", value.c_str());
  356. }
  357. void InterfaceController::setIPv6OptimisticMode(const char *value) {
  358. setOnAllInterfaces(ipv6_proc_path, "optimistic_dad", value);
  359. setOnAllInterfaces(ipv6_proc_path, "use_optimistic", value);
  360. }
  361. StatusOr<std::vector<std::string>> InterfaceController::getIfaceNames() {
  362. std::vector<std::string> ifaceNames;
  363. DIR* d;
  364. struct dirent* de;
  365. if (!(d = opendir("/sys/class/net"))) {
  366. return statusFromErrno(errno, "Cannot open iface directory");
  367. }
  368. while ((de = readdir(d))) {
  369. if ((de->d_type != DT_DIR) && (de->d_type != DT_LNK)) continue;
  370. if (de->d_name[0] == '.') continue;
  371. ifaceNames.push_back(std::string(de->d_name));
  372. }
  373. closedir(d);
  374. return ifaceNames;
  375. }
  376. StatusOr<std::map<std::string, uint32_t>> InterfaceController::getIfaceList() {
  377. std::map<std::string, uint32_t> ifacePairs;
  378. ASSIGN_OR_RETURN(auto ifaceNames, getIfaceNames());
  379. for (const auto& name : ifaceNames) {
  380. uint32_t ifaceIndex = if_nametoindex(name.c_str());
  381. if (ifaceIndex) {
  382. ifacePairs.insert(std::pair<std::string, uint32_t>(name, ifaceIndex));
  383. }
  384. }
  385. return ifacePairs;
  386. }
  387. namespace {
  388. std::string hwAddrToStr(unsigned char* hwaddr) {
  389. return StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3],
  390. hwaddr[4], hwaddr[5]);
  391. }
  392. int ipv4NetmaskToPrefixLength(in_addr_t mask) {
  393. int prefixLength = 0;
  394. uint32_t m = ntohl(mask);
  395. while (m & (1 << 31)) {
  396. prefixLength++;
  397. m = m << 1;
  398. }
  399. return prefixLength;
  400. }
  401. std::string toStdString(const String16& s) {
  402. return std::string(String8(s.string()));
  403. }
  404. } // namespace
  405. Status InterfaceController::setCfg(const InterfaceConfigurationParcel& cfg) {
  406. const auto& sys = sSyscalls.get();
  407. ASSIGN_OR_RETURN(auto fd, sys.socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
  408. struct ifreq ifr = {
  409. .ifr_addr = {.sa_family = AF_INET}, // Clear the IPv4 address.
  410. };
  411. strlcpy(ifr.ifr_name, cfg.ifName.c_str(), IFNAMSIZ);
  412. // Make sure that clear IPv4 address before set flag
  413. // SIOCGIFFLAGS might override ifr and caused clear IPv4 addr ioctl error
  414. RETURN_IF_NOT_OK(sys.ioctl(fd, SIOCSIFADDR, &ifr));
  415. if (!cfg.flags.empty()) {
  416. RETURN_IF_NOT_OK(sys.ioctl(fd, SIOCGIFFLAGS, &ifr));
  417. uint16_t flags = ifr.ifr_flags;
  418. for (const auto& flag : cfg.flags) {
  419. if (flag == toStdString(INetd::IF_STATE_UP())) {
  420. ifr.ifr_flags = ifr.ifr_flags | IFF_UP;
  421. } else if (flag == toStdString(INetd::IF_STATE_DOWN())) {
  422. ifr.ifr_flags = (ifr.ifr_flags & (~IFF_UP));
  423. }
  424. }
  425. if (ifr.ifr_flags != flags) {
  426. RETURN_IF_NOT_OK(sys.ioctl(fd, SIOCSIFFLAGS, &ifr));
  427. }
  428. }
  429. RETURN_STATUS_IF_IFCERROR(
  430. ifc_add_address(cfg.ifName.c_str(), cfg.ipv4Addr.c_str(), cfg.prefixLength));
  431. return ok;
  432. }
  433. StatusOr<InterfaceConfigurationParcel> InterfaceController::getCfg(const std::string& ifName) {
  434. struct in_addr addr = {};
  435. int prefixLength = 0;
  436. unsigned char hwaddr[ETH_ALEN] = {};
  437. unsigned flags = 0;
  438. InterfaceConfigurationParcel cfgResult;
  439. const auto& sys = sSyscalls.get();
  440. ASSIGN_OR_RETURN(auto fd, sys.socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
  441. struct ifreq ifr = {};
  442. strlcpy(ifr.ifr_name, ifName.c_str(), IFNAMSIZ);
  443. if (isOk(sys.ioctl(fd, SIOCGIFADDR, &ifr))) {
  444. addr.s_addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
  445. }
  446. if (isOk(sys.ioctl(fd, SIOCGIFNETMASK, &ifr))) {
  447. prefixLength =
  448. ipv4NetmaskToPrefixLength(((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr);
  449. }
  450. if (isOk(sys.ioctl(fd, SIOCGIFFLAGS, &ifr))) {
  451. flags = ifr.ifr_flags;
  452. }
  453. // ETH_ALEN is for ARPHRD_ETHER, it is better to check the sa_family.
  454. // However, we keep old design for the consistency.
  455. if (isOk(sys.ioctl(fd, SIOCGIFHWADDR, &ifr))) {
  456. memcpy((void*) hwaddr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
  457. } else {
  458. ALOGW("Failed to retrieve HW addr for %s (%s)", ifName.c_str(), strerror(errno));
  459. }
  460. cfgResult.ifName = ifName;
  461. cfgResult.hwAddr = hwAddrToStr(hwaddr);
  462. cfgResult.ipv4Addr = std::string(inet_ntoa(addr));
  463. cfgResult.prefixLength = prefixLength;
  464. cfgResult.flags.push_back(flags & IFF_UP ? toStdString(INetd::IF_STATE_UP())
  465. : toStdString(INetd::IF_STATE_DOWN()));
  466. if (flags & IFF_BROADCAST) cfgResult.flags.push_back(toStdString(INetd::IF_FLAG_BROADCAST()));
  467. if (flags & IFF_LOOPBACK) cfgResult.flags.push_back(toStdString(INetd::IF_FLAG_LOOPBACK()));
  468. if (flags & IFF_POINTOPOINT)
  469. cfgResult.flags.push_back(toStdString(INetd::IF_FLAG_POINTOPOINT()));
  470. if (flags & IFF_RUNNING) cfgResult.flags.push_back(toStdString(INetd::IF_FLAG_RUNNING()));
  471. if (flags & IFF_MULTICAST) cfgResult.flags.push_back(toStdString(INetd::IF_FLAG_MULTICAST()));
  472. return cfgResult;
  473. }
  474. int InterfaceController::clearAddrs(const std::string& ifName) {
  475. return ifc_clear_addresses(ifName.c_str());
  476. }
  477. } // namespace net
  478. } // namespace android