FreeBsdWifiScanner.cpp (4160B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // Developed by J.R. Oldroyd <fbsd@opal.com>, December 2012. 6 7 // For FreeBSD we use the getifaddrs(3) to obtain the list of interfaces 8 // and then check for those with an 802.11 media type and able to return 9 // a list of stations. This is similar to ifconfig(8). 10 11 #include <sys/types.h> 12 #include <sys/ioctl.h> 13 #include <sys/socket.h> 14 #include <net/if.h> 15 #include <net/if_media.h> 16 #ifdef __DragonFly__ 17 # include <netproto/802_11/ieee80211_ioctl.h> 18 #else 19 # include <net80211/ieee80211_ioctl.h> 20 #endif 21 22 #include <ifaddrs.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include "FreeBsdWifiScanner.h" 27 #include "nsWifiAccessPoint.h" 28 #include "nsWifiMonitor.h" 29 30 using namespace mozilla; 31 32 #define LOG(args) MOZ_LOG(gWifiMonitorLog, mozilla::LogLevel::Debug, args) 33 34 WifiScannerImpl::WifiScannerImpl() {}; 35 WifiScannerImpl::~WifiScannerImpl() {}; 36 37 nsresult WifiScannerImpl::GetAccessPointsFromWLAN( 38 nsTArray<RefPtr<nsIWifiAccessPoint>>& accessPoints) { 39 // get list of interfaces 40 struct ifaddrs* ifal; 41 if (getifaddrs(&ifal) < 0) { 42 return NS_ERROR_FAILURE; 43 } 44 45 accessPoints.Clear(); 46 47 // loop through the interfaces 48 nsresult rv = NS_ERROR_FAILURE; 49 struct ifaddrs* ifa; 50 for (ifa = ifal; ifa; ifa = ifa->ifa_next) { 51 // limit to one interface per address 52 if (ifa->ifa_addr->sa_family != AF_LINK) { 53 continue; 54 } 55 56 // store interface name in socket structure 57 struct ifreq ifr; 58 memset(&ifr, 0, sizeof(ifr)); 59 strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name)); 60 ifr.ifr_addr.sa_family = AF_LOCAL; 61 62 // open socket to interface 63 int s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0); 64 if (s < 0) { 65 continue; 66 } 67 68 // clear interface media structure 69 struct ifmediareq ifmr; 70 memset(&ifmr, 0, sizeof(ifmr)); 71 strncpy(ifmr.ifm_name, ifa->ifa_name, sizeof(ifmr.ifm_name)); 72 73 // get interface media information 74 if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 75 close(s); 76 continue; 77 } 78 79 // check interface is a WiFi interface 80 if (IFM_TYPE(ifmr.ifm_active) != IFM_IEEE80211) { 81 close(s); 82 continue; 83 } 84 85 // perform WiFi scan 86 struct ieee80211req i802r; 87 char iscanbuf[32 * 1024]; 88 memset(&i802r, 0, sizeof(i802r)); 89 strncpy(i802r.i_name, ifa->ifa_name, sizeof(i802r.i_name)); 90 i802r.i_type = IEEE80211_IOC_SCAN_RESULTS; 91 i802r.i_data = iscanbuf; 92 i802r.i_len = sizeof(iscanbuf); 93 if (ioctl(s, SIOCG80211, &i802r) < 0) { 94 close(s); 95 continue; 96 } 97 98 // close socket 99 close(s); 100 101 // loop through WiFi networks and build geoloc-lookup structure 102 char* vsr = (char*)i802r.i_data; 103 unsigned len = i802r.i_len; 104 while (len >= sizeof(struct ieee80211req_scan_result)) { 105 struct ieee80211req_scan_result* isr = 106 (struct ieee80211req_scan_result*)vsr; 107 108 // determine size of this entry 109 char* id; 110 int idlen; 111 if (isr->isr_meshid_len) { 112 id = vsr + isr->isr_ie_off + isr->isr_ssid_len; 113 idlen = isr->isr_meshid_len; 114 } else { 115 id = vsr + isr->isr_ie_off; 116 idlen = isr->isr_ssid_len; 117 } 118 119 // copy network data 120 char ssid[IEEE80211_NWID_LEN + 1]; 121 strncpy(ssid, id, idlen); 122 ssid[idlen] = '\0'; 123 nsWifiAccessPoint* ap = new nsWifiAccessPoint(); 124 ap->setSSID(ssid, strlen(ssid)); 125 ap->setMac(isr->isr_bssid); 126 ap->setSignal(isr->isr_rssi); 127 accessPoints.AppendElement(ap); 128 rv = NS_OK; 129 130 // log the data 131 LOG( 132 ("FreeBSD access point: " 133 "SSID: %s, MAC: %02x-%02x-%02x-%02x-%02x-%02x, " 134 "Strength: %d, Channel: %dMHz\n", 135 ssid, isr->isr_bssid[0], isr->isr_bssid[1], isr->isr_bssid[2], 136 isr->isr_bssid[3], isr->isr_bssid[4], isr->isr_bssid[5], 137 isr->isr_rssi, isr->isr_freq)); 138 139 // increment pointers 140 len -= isr->isr_len; 141 vsr += isr->isr_len; 142 } 143 } 144 145 freeifaddrs(ifal); 146 147 return rv; 148 }