ConnectionList CPosixNetworkManager::GetConnections()
{
  FindNetworkInterfaces();
  if (CanManageConnections())
    RestoreSavedConnection();
  else
    RestoreSystemConnection();
  return m_connections;
}
Ejemplo n.º 2
0
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
CPosixNetworkManager::CPosixNetworkManager()
{
  CLog::Log(LOGDEBUG, "NetworkManager: PosixNetworkManager created");
  m_socket = socket(AF_INET, SOCK_DGRAM, 0);
  m_post_failed = false;
  FindNetworkInterfaces();
  if (CanManageConnections())
    RestoreSavedConnection();
  else
    RestoreSystemConnection();
}
Ejemplo n.º 3
0
bool CPosixNetworkManager::FindWifiConnections(const char *interfaceName)
{
  bool managed = CanManageConnections();
  // Query the wireless extentsions 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, 0x00, sizeof(rangebuffer));
  iwr.u.data.pointer = (caddr_t) rangebuffer;
  iwr.u.data.length = sizeof(rangebuffer);
  iwr.u.data.flags = 0;
  strncpy(iwr.ifr_name, interfaceName, IFNAMSIZ);
  if (ioctl(m_socket, SIOCGIWRANGE, &iwr) < 0)
  {
    CLog::Log(LOGWARNING, "%-8.16s  Driver has no Wireless Extension version information.",
      interfaceName);
    return false;
  }

  // Scan for wireless access points
  memset(&iwr, 0x00, sizeof(iwr));
  strncpy(iwr.ifr_name, interfaceName, IFNAMSIZ);
  if (ioctl(m_socket, SIOCSIWSCAN, &iwr) < 0)
  {
    CLog::Log(LOGWARNING, "Cannot initiate wireless scan: ioctl[SIOCSIWSCAN]: %s", strerror(errno));
    return false;
  }

  // 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. Were'e 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 false;
    }

    strncpy(iwr.ifr_name, interfaceName, IFNAMSIZ);
    iwr.u.data.pointer = res_buf;
    iwr.u.data.length = res_buf_len;
    iwr.u.data.flags = 0;
    int x = ioctl(m_socket, 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 false;
    }
  }

  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

  bool first = true;
  char essid[IW_ESSID_MAX_SIZE+1];
  char macaddress[256];
  int  quality = 0, signalLevel = 0;
  EncryptionType encryption = NETWORK_CONNECTION_ENCRYPTION_NONE;

  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 extentsions 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
    {
      memcpy(&iwe_buf, pos, sizeof(struct iw_event));
      custom += IW_EV_POINT_OFF;
    }

    switch (iwe->cmd)
    {

      // Get the access point MAC addresses
      case SIOCGIWAP:
      {
        // this is the 1st cmp we get, so we have to play games
        // and push back our parsed results on the next one, but
        // we need to save the macaddress so we push the right one.
        char cur_macaddress[256] = {0};
        // macAddress is big-endian, write in byte chunks
        sprintf(cur_macaddress, "%02X:%02X:%02X:%02X:%02X:%02X",
          iwe->u.ap_addr.sa_data[0], iwe->u.ap_addr.sa_data[1],
          iwe->u.ap_addr.sa_data[2], iwe->u.ap_addr.sa_data[3],
          iwe->u.ap_addr.sa_data[4], iwe->u.ap_addr.sa_data[5]);

        if (first)
        {
          first = false;
          memcpy(macaddress, cur_macaddress, sizeof(macaddress));
        }
        else
        {
          m_connections.push_back(CConnectionPtr(new CPosixConnection(managed,
            m_socket, interfaceName, macaddress, essid,
            NETWORK_CONNECTION_TYPE_WIFI, encryption, quality)));
          memcpy(macaddress, cur_macaddress, sizeof(macaddress));
        }
        // reset encryption for parsing next access point
        encryption = NETWORK_CONNECTION_ENCRYPTION_NONE;
        signalLevel = 0;
        break;
      }

      // Get ESSID
      case SIOCGIWESSID:
      {
        memset(essid, 0x00, sizeof(essid));
        if ((custom) && (iwe->u.essid.length))
          memcpy(essid, custom, iwe->u.essid.length);
        break;
      }

      // Quality part of statistics
      case IWEVQUAL:
      {
        quality = iwe->u.qual.qual;
        signalLevel = iwe->u.qual.level;
        break;
      }

      // Get encoding token & mode
      case SIOCGIWENCODE:
      {
        if (!(iwe->u.data.flags & IW_ENCODE_DISABLED) && encryption == NETWORK_CONNECTION_ENCRYPTION_NONE)
          encryption = NETWORK_CONNECTION_ENCRYPTION_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 != NETWORK_CONNECTION_ENCRYPTION_WPA2)
                encryption = NETWORK_CONNECTION_ENCRYPTION_WPA;
              break;
            case 0x30: // WPA2
              encryption = NETWORK_CONNECTION_ENCRYPTION_WPA2;
              break;
          }
          offset += custom[offset+1] + 2;
        }
      }
    }
    pos += iwe->len;
  }

  if (!first)
  {
    m_connections.push_back(CConnectionPtr(new CPosixConnection(managed,
      m_socket, interfaceName, macaddress, essid,
      NETWORK_CONNECTION_TYPE_WIFI, encryption, quality)));
  }

  free(res_buf);
  res_buf = NULL;
  return true;
}
Ejemplo n.º 4
0
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);
}