1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/base/net_util.h" 6 7 #include <set> 8 #include <sys/types.h> 9 10 #include "base/files/file_path.h" 11 #include "base/logging.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_tokenizer.h" 14 #include "base/strings/string_util.h" 15 #include "base/threading/thread_restrictions.h" 16 #include "net/base/escape.h" 17 #include "net/base/ip_endpoint.h" 18 #include "net/base/net_errors.h" 19 #include "url/gurl.h" 20 21 #if !defined(OS_ANDROID) && !defined(OS_NACL) 22 #include <ifaddrs.h> 23 #include <net/if.h> 24 #include <netinet/in.h> 25 #endif 26 27 #if defined(OS_MACOSX) && !defined(OS_IOS) 28 #include <net/if_media.h> 29 #include <netinet/in_var.h> 30 #include <sys/ioctl.h> 31 #endif 32 33 #if defined(OS_ANDROID) 34 #include "net/android/network_library.h" 35 #endif 36 37 namespace net { 38 39 namespace { 40 41 #if !defined(OS_ANDROID) 42 43 struct NetworkInterfaceInfo { 44 NetworkInterfaceInfo() : permanent(true) { } 45 46 bool permanent; // IPv6 has notion of temporary address. If the address is 47 // IPv6 and it's temporary this field will be false. 48 NetworkInterface interface; 49 }; 50 51 // This method will remove permanent IPv6 addresses if a temporary address 52 // is available for same network interface. 53 void RemovePermanentIPv6AddressesWhereTemporaryExists( 54 std::vector<NetworkInterfaceInfo>* infos) { 55 if (!infos || infos->empty()) 56 return; 57 58 // Build a set containing the names of interfaces with a temp IPv6 address 59 std::set<std::string> ifaces_with_temp_addrs; 60 std::vector<NetworkInterfaceInfo>::iterator i; 61 for (i = infos->begin(); i != infos->end(); ++i) { 62 if (!i->permanent && i->interface.address.size() == kIPv6AddressSize) { 63 ifaces_with_temp_addrs.insert(i->interface.name); 64 } 65 } 66 67 // If there are no such interfaces then there's no further work. 68 if (ifaces_with_temp_addrs.empty()) 69 return; 70 71 // Search for permenent addresses belonging to same network interface. 72 for (i = infos->begin(); i != infos->end(); ) { 73 // If the address is IPv6 and it's permanent and there is temporary 74 // address for it, then we can remove this address. 75 if ((i->interface.address.size() == kIPv6AddressSize) && i->permanent && 76 (ifaces_with_temp_addrs.find(i->interface.name) != 77 ifaces_with_temp_addrs.end())) { 78 i = infos->erase(i); 79 } else { 80 ++i; 81 } 82 } 83 } 84 85 #endif 86 87 #if defined(OS_MACOSX) && !defined(OS_IOS) 88 89 NetworkChangeNotifier::ConnectionType GetNetworkInterfaceType( 90 int addr_family, const std::string& interface_name) { 91 NetworkChangeNotifier::ConnectionType type = 92 NetworkChangeNotifier::CONNECTION_UNKNOWN; 93 94 struct ifmediareq ifmr = {}; 95 strncpy(ifmr.ifm_name, interface_name.c_str(), sizeof(ifmr.ifm_name) - 1); 96 97 int s = socket(addr_family, SOCK_DGRAM, 0); 98 if (s == -1) { 99 return type; 100 } 101 102 if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1) { 103 if (ifmr.ifm_current & IFM_IEEE80211) { 104 type = NetworkChangeNotifier::CONNECTION_WIFI; 105 } else if (ifmr.ifm_current & IFM_ETHER) { 106 type = NetworkChangeNotifier::CONNECTION_ETHERNET; 107 } 108 } 109 close(s); 110 return type; 111 } 112 113 #endif 114 115 } // namespace 116 117 bool GetNetworkList(NetworkInterfaceList* networks, int policy) { 118 #if defined(OS_NACL) 119 NOTIMPLEMENTED(); 120 return false; 121 #elif defined(OS_ANDROID) 122 std::string network_list = android::GetNetworkList(); 123 base::StringTokenizer network_interfaces(network_list, "\n"); 124 while (network_interfaces.GetNext()) { 125 std::string network_item = network_interfaces.token(); 126 base::StringTokenizer network_tokenizer(network_item, "\t"); 127 CHECK(network_tokenizer.GetNext()); 128 std::string name = network_tokenizer.token(); 129 130 CHECK(network_tokenizer.GetNext()); 131 std::string interface_address = network_tokenizer.token(); 132 IPAddressNumber address; 133 size_t network_prefix = 0; 134 CHECK(ParseCIDRBlock(network_tokenizer.token(), 135 &address, 136 &network_prefix)); 137 138 CHECK(network_tokenizer.GetNext()); 139 uint32 index = 0; 140 CHECK(base::StringToUint(network_tokenizer.token(), &index)); 141 142 networks->push_back( 143 NetworkInterface(name, name, index, 144 NetworkChangeNotifier::CONNECTION_UNKNOWN, 145 address, network_prefix)); 146 } 147 return true; 148 #else 149 // getifaddrs() may require IO operations. 150 base::ThreadRestrictions::AssertIOAllowed(); 151 152 int ioctl_socket = -1; 153 if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) { 154 // we need a socket to query information about temporary address. 155 ioctl_socket = socket(AF_INET6, SOCK_DGRAM, 0); 156 DCHECK_GT(ioctl_socket, 0); 157 } 158 159 ifaddrs *interfaces; 160 if (getifaddrs(&interfaces) < 0) { 161 PLOG(ERROR) << "getifaddrs"; 162 return false; 163 } 164 165 std::vector<NetworkInterfaceInfo> network_infos; 166 167 // Enumerate the addresses assigned to network interfaces which are up. 168 for (ifaddrs *interface = interfaces; 169 interface != NULL; 170 interface = interface->ifa_next) { 171 // Skip loopback interfaces, and ones which are down. 172 if (!(IFF_UP & interface->ifa_flags)) 173 continue; 174 if (IFF_LOOPBACK & interface->ifa_flags) 175 continue; 176 // Skip interfaces with no address configured. 177 struct sockaddr* addr = interface->ifa_addr; 178 if (!addr) 179 continue; 180 181 // Skip unspecified addresses (i.e. made of zeroes) and loopback addresses 182 // configured on non-loopback interfaces. 183 int addr_size = 0; 184 if (addr->sa_family == AF_INET6) { 185 struct sockaddr_in6* addr_in6 = 186 reinterpret_cast<struct sockaddr_in6*>(addr); 187 struct in6_addr* sin6_addr = &addr_in6->sin6_addr; 188 addr_size = sizeof(*addr_in6); 189 if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || 190 IN6_IS_ADDR_UNSPECIFIED(sin6_addr)) { 191 continue; 192 } 193 } else if (addr->sa_family == AF_INET) { 194 struct sockaddr_in* addr_in = 195 reinterpret_cast<struct sockaddr_in*>(addr); 196 addr_size = sizeof(*addr_in); 197 if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK || 198 addr_in->sin_addr.s_addr == 0) { 199 continue; 200 } 201 } else { 202 // Skip non-IP addresses. 203 continue; 204 } 205 206 const std::string& name = interface->ifa_name; 207 // Filter out VMware interfaces, typically named vmnet1 and vmnet8. 208 if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) && 209 ((name.find("vmnet") != std::string::npos) || 210 (name.find("vnic") != std::string::npos))) { 211 continue; 212 } 213 214 NetworkInterfaceInfo network_info; 215 NetworkChangeNotifier::ConnectionType connection_type = 216 NetworkChangeNotifier::CONNECTION_UNKNOWN; 217 #if defined(OS_MACOSX) && !defined(OS_IOS) 218 // Check if this is a temporary address. Currently this is only supported 219 // on Mac. 220 if ((policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) && 221 ioctl_socket >= 0 && addr->sa_family == AF_INET6) { 222 struct in6_ifreq ifr = {}; 223 strncpy(ifr.ifr_name, interface->ifa_name, sizeof(ifr.ifr_name) - 1); 224 memcpy(&ifr.ifr_ifru.ifru_addr, interface->ifa_addr, 225 interface->ifa_addr->sa_len); 226 int rv = ioctl(ioctl_socket, SIOCGIFAFLAG_IN6, &ifr); 227 if (rv >= 0) { 228 network_info.permanent = !(ifr.ifr_ifru.ifru_flags & IN6_IFF_TEMPORARY); 229 } 230 } 231 232 connection_type = GetNetworkInterfaceType(addr->sa_family, name); 233 #endif 234 235 IPEndPoint address; 236 if (address.FromSockAddr(addr, addr_size)) { 237 uint8 net_mask = 0; 238 if (interface->ifa_netmask) { 239 // If not otherwise set, assume the same sa_family as ifa_addr. 240 if (interface->ifa_netmask->sa_family == 0) { 241 interface->ifa_netmask->sa_family = addr->sa_family; 242 } 243 IPEndPoint netmask; 244 if (netmask.FromSockAddr(interface->ifa_netmask, addr_size)) { 245 net_mask = MaskPrefixLength(netmask.address()); 246 } 247 } 248 network_info.interface = NetworkInterface( 249 name, name, if_nametoindex(name.c_str()), 250 connection_type, address.address(), net_mask); 251 252 network_infos.push_back(NetworkInterfaceInfo(network_info)); 253 } 254 } 255 freeifaddrs(interfaces); 256 if (ioctl_socket >= 0) { 257 close(ioctl_socket); 258 } 259 260 if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) { 261 RemovePermanentIPv6AddressesWhereTemporaryExists(&network_infos); 262 } 263 264 for (size_t i = 0; i < network_infos.size(); ++i) { 265 networks->push_back(network_infos[i].interface); 266 } 267 return true; 268 #endif 269 } 270 271 WifiPHYLayerProtocol GetWifiPHYLayerProtocol() { 272 return WIFI_PHY_LAYER_PROTOCOL_UNKNOWN; 273 } 274 275 } // namespace net 276