nsWifiScannerFreeBSD.cpp 4.6 KB

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