int wifiAdapter(TCHAR *strAdapter) { DWORD ret; ULONG buffLen = 0; if ((ret = GetAdaptersInfo(NULL, &buffLen)) != ERROR_BUFFER_OVERFLOW) return 0; IP_ADAPTER_INFO* pInfo = (IP_ADAPTER_INFO*) malloc(buffLen); if ((ret = GetAdaptersInfo(pInfo, &buffLen)) != ERROR_SUCCESS){ free(pInfo); return 0; } ret = 0; while (pInfo){ MultiByteToWideChar(CP_UTF8, 0, pInfo->AdapterName, -1, (LPWSTR) strAdapter, 200); if (IsWireless(strAdapter)){ ret = 1; break; } pInfo = pInfo->Next; } free(pInfo); return ret; }
void CNetworkInterfaceLinux::WriteSettings(FILE* fw, NetworkAssignment assignment, std::string& ipAddress, std::string& networkMask, std::string& defaultGateway, std::string& essId, std::string& key, EncMode& encryptionMode) { if (assignment == NETWORK_DHCP) { fprintf(fw, "iface %s inet dhcp\n", GetName().c_str()); } else if (assignment == NETWORK_STATIC) { fprintf(fw, "iface %s inet static\n", GetName().c_str()); fprintf(fw, " address %s\n", ipAddress.c_str()); fprintf(fw, " netmask %s\n", networkMask.c_str()); fprintf(fw, " gateway %s\n", defaultGateway.c_str()); } if (assignment != NETWORK_DISABLED && IsWireless()) { if (encryptionMode == ENC_NONE) { fprintf(fw, " wireless-essid %s\n", essId.c_str()); } else if (encryptionMode == ENC_WEP) { fprintf(fw, " wireless-essid %s\n", essId.c_str()); fprintf(fw, " wireless-key s:%s\n", key.c_str()); } else if (encryptionMode == ENC_WPA || encryptionMode == ENC_WPA2) { fprintf(fw, " wpa-ssid %s\n", essId.c_str()); fprintf(fw, " wpa-psk %s\n", key.c_str()); fprintf(fw, " wpa-proto %s\n", encryptionMode == ENC_WPA ? "WPA" : "WPA2"); } } if (assignment != NETWORK_DISABLED) fprintf(fw, "auto %s\n\n", GetName().c_str()); }
std::vector<NetworkAccessPoint> CNetworkInterfaceLinux::GetAccessPoints(void) { std::vector<NetworkAccessPoint> result; if (!IsWireless()) return result; #if defined(TARGET_LINUX) // Query the wireless extension's version number. It will help us when we // parse the resulting events struct iwreq iwr; char rangebuffer[sizeof(iw_range) * 2]; /* Large enough */ struct iw_range* range = (struct iw_range*) rangebuffer; memset(rangebuffer, 0, sizeof(rangebuffer)); iwr.u.data.pointer = (caddr_t) rangebuffer; iwr.u.data.length = sizeof(rangebuffer); iwr.u.data.flags = 0; strncpy(iwr.ifr_name, GetName().c_str(), IFNAMSIZ); iwr.ifr_name[IFNAMSIZ - 1] = 0; if (ioctl(m_network->GetSocket(), SIOCGIWRANGE, &iwr) < 0) { CLog::Log(LOGWARNING, "%-8.16s Driver has no Wireless Extension version information.", GetName().c_str()); return result; } // Scan for wireless access points memset(&iwr, 0, sizeof(iwr)); strncpy(iwr.ifr_name, GetName().c_str(), IFNAMSIZ); iwr.ifr_name[IFNAMSIZ - 1] = 0; if (ioctl(m_network->GetSocket(), SIOCSIWSCAN, &iwr) < 0) { // Triggering scanning is a privileged operation (root only) if (errno == EPERM) CLog::Log(LOGWARNING, "Cannot initiate wireless scan: ioctl[SIOCSIWSCAN]: %s. Try running as root", strerror(errno)); else CLog::Log(LOGWARNING, "Cannot initiate wireless scan: ioctl[SIOCSIWSCAN]: %s", strerror(errno)); return result; } // Get the results of the scanning. Three scenarios: // 1. There's not enough room in the result buffer (E2BIG) // 2. The scanning is not complete (EAGAIN) and we need to try again. We cap this with 15 seconds. // 3. We're good. int duration = 0; // ms unsigned char* res_buf = NULL; int res_buf_len = IW_SCAN_MAX_DATA; while (duration < 15000) { if (!res_buf) res_buf = (unsigned char*) malloc(res_buf_len); if (res_buf == NULL) { CLog::Log(LOGWARNING, "Cannot alloc memory for wireless scanning"); return result; } strncpy(iwr.ifr_name, GetName().c_str(), IFNAMSIZ); iwr.ifr_name[IFNAMSIZ - 1] = 0; iwr.u.data.pointer = res_buf; iwr.u.data.length = res_buf_len; iwr.u.data.flags = 0; int x = ioctl(m_network->GetSocket(), SIOCGIWSCAN, &iwr); if (x == 0) break; if (errno == E2BIG && res_buf_len < 100000) { free(res_buf); res_buf = NULL; res_buf_len *= 2; CLog::Log(LOGDEBUG, "Scan results did not fit - trying larger buffer (%lu bytes)", (unsigned long) res_buf_len); } else if (errno == EAGAIN) { usleep(250000); // sleep for 250ms duration += 250; } else { CLog::Log(LOGWARNING, "Cannot get wireless scan results: ioctl[SIOCGIWSCAN]: %s", strerror(errno)); free(res_buf); return result; } } size_t len = iwr.u.data.length; // total length of the wireless events from the scan results unsigned char* pos = res_buf; // pointer to the current event (about 10 per wireless network) unsigned char* end = res_buf + len; // marks the end of the scan results unsigned char* custom; // pointer to the event payload struct iw_event iwe_buf, *iwe = &iwe_buf; // buffer to hold individual events std::string essId; std::string macAddress; int signalLevel = 0; EncMode encryption = ENC_NONE; int channel = 0; while (pos + IW_EV_LCP_LEN <= end) { /* Event data may be unaligned, so make a local, aligned copy * before processing. */ // copy event prefix (size of event minus IOCTL fixed payload) memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); if (iwe->len <= IW_EV_LCP_LEN) break; // if the payload is nontrivial (i.e. > 16 octets) assume it comes after a pointer custom = pos + IW_EV_POINT_LEN; if (range->we_version_compiled > 18 && (iwe->cmd == SIOCGIWESSID || iwe->cmd == SIOCGIWENCODE || iwe->cmd == IWEVGENIE || iwe->cmd == IWEVCUSTOM)) { /* Wireless extensions v19 removed the pointer from struct iw_point */ char *data_pos = (char *) &iwe_buf.u.data.length; int data_len = data_pos - (char *) &iwe_buf; memcpy(data_pos, pos + IW_EV_LCP_LEN, sizeof(struct iw_event) - data_len); } else { // copy the rest of the event and point custom toward the payload offset memcpy(&iwe_buf, pos, sizeof(struct iw_event)); custom += IW_EV_POINT_OFF; } // Interpret the payload based on event type. Each access point generates ~12 different events switch (iwe->cmd) { // Get access point MAC addresses case SIOCGIWAP: { // This event marks a new access point, so push back the old information if (!macAddress.empty()) result.push_back(NetworkAccessPoint(essId, macAddress, signalLevel, encryption, channel)); unsigned char* mac = (unsigned char*)iwe->u.ap_addr.sa_data; // macAddress is big-endian, write in byte chunks macAddress = StringUtils::Format("%02x-%02x-%02x-%02x-%02x-%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); // Reset the remaining fields essId = ""; encryption = ENC_NONE; signalLevel = 0; channel = 0; break; } // Get operation mode case SIOCGIWMODE: { // Ignore Ad-Hoc networks (1 is the magic number for this) if (iwe->u.mode == 1) macAddress = ""; break; } // Get ESSID case SIOCGIWESSID: { char essid[IW_ESSID_MAX_SIZE+1]; memset(essid, '\0', sizeof(essid)); if ((custom) && (iwe->u.essid.length)) { memcpy(essid, custom, iwe->u.essid.length); essId = essid; } break; } // Quality part of statistics case IWEVQUAL: { // u.qual.qual is scaled to a vendor-specific RSSI_Max, so use u.qual.level signalLevel = iwe->u.qual.level - 0x100; // and remember we use 8-bit arithmetic break; } // Get channel/frequency (Hz) // This gets called twice per network, what's the difference between the two? case SIOCGIWFREQ: { float freq = ((float)iwe->u.freq.m) * pow(10.0, iwe->u.freq.e); if (freq > 1000) channel = NetworkAccessPoint::FreqToChannel(freq); else channel = (int)freq; // Some drivers report channel instead of frequency break; } // Get encoding token & mode case SIOCGIWENCODE: { if (!(iwe->u.data.flags & IW_ENCODE_DISABLED) && encryption == ENC_NONE) encryption = ENC_WEP; break; } // Generic IEEE 802.11 information element (IE) for WPA, RSN, WMM, ... case IWEVGENIE: { int offset = 0; // Loop on each IE, each IE is minimum 2 bytes while (offset <= (iwe_buf.u.data.length - 2)) { switch (custom[offset]) { case 0xdd: /* WPA1 */ if (encryption != ENC_WPA2) encryption = ENC_WPA; break; case 0x30: /* WPA2 */ encryption = ENC_WPA2; } // Skip over this IE to the next one in the list offset += custom[offset+1] + 2; } } } pos += iwe->len; } if (!macAddress.empty()) result.push_back(NetworkAccessPoint(essId, macAddress, signalLevel, encryption, channel)); free(res_buf); res_buf = NULL; #endif return result; }
void CPosixNetworkManager::FindNetworkInterfaces() { m_connections.clear(); FILE *fp = fopen("/proc/net/dev", "r"); if (!fp) return; int n, linenum = 0; char *line = NULL; size_t linel = 0; char *interfaceName; bool managed = CanManageConnections(); while (getdelim(&line, &linel, '\n', fp) > 0) { // skip first two lines if (linenum++ < 2) continue; // search where the word begins interfaceName = line; while (isspace(*interfaceName)) ++interfaceName; // read word until : n = strcspn(interfaceName, ": \t"); interfaceName[n] = 0; #if defined(TARGET_ANDROID) // only test ethX and wlanX interfaces, // anything else is non-standard and we do not care about it. if (strncmp(interfaceName, "eth", 3) != 0 && strncmp(interfaceName, "wlan", 4) != 0) continue; #endif // make sure the device has ethernet encapsulation struct ifreq ifr; memset(&ifr, 0x00, sizeof(ifr)); strcpy(ifr.ifr_name, interfaceName); std::string essid = "Wired"; ConnectionType connection = NETWORK_CONNECTION_TYPE_WIRED; EncryptionType encryption = NETWORK_CONNECTION_ENCRYPTION_NONE; if (ioctl(m_socket, SIOCGIFHWADDR, &ifr) >= 0) { #if defined(TARGET_ANDROID) // Android cannot SIOCSIWSCAN (permissions error) // So just flag as wifi with unknown encryption and use it. if (IsWireless(m_socket, interfaceName)) { essid = "Wifi"; connection = NETWORK_CONNECTION_TYPE_WIFI; encryption = NETWORK_CONNECTION_ENCRYPTION_UNKNOWN; } #else if (IsWireless(m_socket, interfaceName)) { // get the list of access points on this interface, try this 3 times int retryCount = 0; while (!FindWifiConnections(interfaceName) && retryCount < 3) retryCount++; } else #endif { // and ignore loopback, we also include ARPHRD_80211 but that will only // apply if we are running on android. if ((ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER || ifr.ifr_hwaddr.sa_family == ARPHRD_80211) && !(ifr.ifr_flags & IFF_LOOPBACK)) { char macaddress[1024] = {0}; if (ioctl(m_socket, SIOCGIFHWADDR, &ifr) >= 0) { // format up 'wire.<mac address>.<interface name> sprintf(macaddress, "%02X:%02X:%02X:%02X:%02X:%02X", ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); } /* CLog::Log(LOGDEBUG, "CPosixNetworkManager::FindNetworkInterfaces, " "interfaceName(%s), macaddress(%s), essid(%s)", interfaceName, macaddress, essid.c_str()); */ m_connections.push_back(CConnectionPtr(new CPosixConnection(managed, m_socket, interfaceName, macaddress, essid.c_str(), connection, encryption, 100))); } } } } free(line); fclose(fp); }