netwerk/wifi/nsWifiScannerFreeBSD.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/wifi/nsWifiScannerFreeBSD.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,167 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +// Developed by J.R. Oldroyd <fbsd@opal.com>, December 2012.
     1.9 +
    1.10 +// For FreeBSD we use the getifaddrs(3) to obtain the list of interfaces
    1.11 +// and then check for those with an 802.11 media type and able to return
    1.12 +// a list of stations. This is similar to ifconfig(8).
    1.13 +
    1.14 +#include <sys/types.h>
    1.15 +#include <sys/ioctl.h>
    1.16 +#include <sys/socket.h>
    1.17 +#include <net/if.h>
    1.18 +#include <net/if_media.h>
    1.19 +#include <net80211/ieee80211_ioctl.h>
    1.20 +
    1.21 +#include <ifaddrs.h>
    1.22 +#include <string.h>
    1.23 +#include <unistd.h>
    1.24 +
    1.25 +#include "nsWifiAccessPoint.h"
    1.26 +
    1.27 +using namespace mozilla;
    1.28 +
    1.29 +static nsresult
    1.30 +FreeBSDGetAccessPointData(nsCOMArray<nsWifiAccessPoint> &accessPoints)
    1.31 +{
    1.32 +  // get list of interfaces
    1.33 +  struct ifaddrs *ifal;
    1.34 +  if (getifaddrs(&ifal) < 0) {
    1.35 +    return NS_ERROR_FAILURE;
    1.36 +  }
    1.37 +
    1.38 +  accessPoints.Clear();
    1.39 +
    1.40 +  // loop through the interfaces
    1.41 +  nsresult rv = NS_ERROR_FAILURE;
    1.42 +  struct ifaddrs *ifa;
    1.43 +  for (ifa = ifal; ifa; ifa = ifa->ifa_next) {
    1.44 +    // limit to one interface per address
    1.45 +    if (ifa->ifa_addr->sa_family != AF_LINK) {
    1.46 +      continue;
    1.47 +    }
    1.48 +
    1.49 +    // store interface name in socket structure
    1.50 +    struct ifreq ifr;
    1.51 +    memset(&ifr, 0, sizeof(ifr));
    1.52 +    strncpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
    1.53 +    ifr.ifr_addr.sa_family = AF_LOCAL;
    1.54 +
    1.55 +    // open socket to interface
    1.56 +    int s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
    1.57 +    if (s < 0) {
    1.58 +      continue;
    1.59 +    }
    1.60 +
    1.61 +    // clear interface media structure
    1.62 +    struct ifmediareq ifmr;
    1.63 +    memset(&ifmr, 0, sizeof(ifmr));
    1.64 +    strncpy(ifmr.ifm_name, ifa->ifa_name, sizeof(ifmr.ifm_name));
    1.65 +
    1.66 +    // get interface media information
    1.67 +    if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
    1.68 +      close(s);
    1.69 +      continue;
    1.70 +    }
    1.71 +
    1.72 +    // check interface is a WiFi interface
    1.73 +    if (IFM_TYPE(ifmr.ifm_active) != IFM_IEEE80211) {
    1.74 +      close(s);
    1.75 +      continue;
    1.76 +    }
    1.77 +
    1.78 +    // perform WiFi scan
    1.79 +    struct ieee80211req i802r;
    1.80 +    char iscanbuf[32*1024];
    1.81 +    memset(&i802r, 0, sizeof(i802r));
    1.82 +    strncpy(i802r.i_name, ifa->ifa_name, sizeof(i802r.i_name));
    1.83 +    i802r.i_type = IEEE80211_IOC_SCAN_RESULTS;
    1.84 +    i802r.i_data = iscanbuf;
    1.85 +    i802r.i_len = sizeof(iscanbuf);
    1.86 +    if (ioctl(s, SIOCG80211, &i802r) < 0) {
    1.87 +      close(s);
    1.88 +      continue;
    1.89 +    }
    1.90 +
    1.91 +    // close socket
    1.92 +    close(s);
    1.93 +
    1.94 +    // loop through WiFi networks and build geoloc-lookup structure
    1.95 +    char *vsr = (char *) i802r.i_data;
    1.96 +    unsigned len = i802r.i_len;
    1.97 +    while (len >= sizeof(struct ieee80211req_scan_result)) {
    1.98 +      struct ieee80211req_scan_result *isr =
    1.99 +        (struct ieee80211req_scan_result *) vsr;
   1.100 +
   1.101 +      // determine size of this entry
   1.102 +      char *id;
   1.103 +      int idlen;
   1.104 +      if (isr->isr_meshid_len) {
   1.105 +        id = vsr + isr->isr_ie_off + isr->isr_ssid_len;
   1.106 +        idlen = isr->isr_meshid_len;
   1.107 +      } else {
   1.108 +        id = vsr + isr->isr_ie_off;
   1.109 +        idlen = isr->isr_ssid_len;
   1.110 +      }
   1.111 +
   1.112 +      // copy network data
   1.113 +      char ssid[IEEE80211_NWID_LEN+1];
   1.114 +      strncpy(ssid, id, idlen);
   1.115 +      ssid[idlen] = '\0';
   1.116 +      nsWifiAccessPoint *ap = new nsWifiAccessPoint();
   1.117 +      ap->setSSID(ssid, strlen(ssid));
   1.118 +      ap->setMac(isr->isr_bssid);
   1.119 +      ap->setSignal(isr->isr_rssi);
   1.120 +      accessPoints.AppendObject(ap);
   1.121 +      rv = NS_OK;
   1.122 +
   1.123 +      // log the data
   1.124 +      LOG(( "FreeBSD access point: "
   1.125 +            "SSID: %s, MAC: %02x-%02x-%02x-%02x-%02x-%02x, "
   1.126 +            "Strength: %d, Channel: %dMHz\n",
   1.127 +            ssid, isr->isr_bssid[0], isr->isr_bssid[1], isr->isr_bssid[2],
   1.128 +            isr->isr_bssid[3], isr->isr_bssid[4], isr->isr_bssid[5],
   1.129 +            isr->isr_rssi, isr->isr_freq));
   1.130 +
   1.131 +      // increment pointers
   1.132 +      len -= isr->isr_len;
   1.133 +      vsr += isr->isr_len;
   1.134 +    }
   1.135 +  }
   1.136 +
   1.137 +  freeifaddrs(ifal);
   1.138 +
   1.139 +  return rv;
   1.140 +}
   1.141 +
   1.142 +nsresult
   1.143 +nsWifiMonitor::DoScan()
   1.144 +{
   1.145 +  // Regularly get the access point data.
   1.146 +
   1.147 +  nsCOMArray<nsWifiAccessPoint> lastAccessPoints;
   1.148 +  nsCOMArray<nsWifiAccessPoint> accessPoints;
   1.149 +
   1.150 +  do {
   1.151 +    nsresult rv = FreeBSDGetAccessPointData(accessPoints);
   1.152 +    if (NS_FAILED(rv))
   1.153 +      return rv;
   1.154 +
   1.155 +    bool accessPointsChanged = !AccessPointsEqual(accessPoints, lastAccessPoints);
   1.156 +    ReplaceArray(lastAccessPoints, accessPoints);
   1.157 +
   1.158 +    rv = CallWifiListeners(lastAccessPoints, accessPointsChanged);
   1.159 +    NS_ENSURE_SUCCESS(rv, rv);
   1.160 +
   1.161 +    // wait for some reasonable amount of time. pref?
   1.162 +    LOG(("waiting on monitor\n"));
   1.163 +
   1.164 +    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   1.165 +    mon.Wait(PR_SecondsToInterval(60));
   1.166 +  }
   1.167 +  while (mKeepGoing);
   1.168 +
   1.169 +  return NS_OK;
   1.170 +}

mercurial