首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无线ESSID和使用wireless.h的C语言信号强度

无线ESSID和使用wireless.h的C语言信号强度
EN

Stack Overflow用户
提问于 2019-11-28 19:22:57
回答 2查看 611关注 0票数 3

我目前有一个应用程序,它获得essid和信号强度使用popen(nmcli...)我正在尝试使用wireless.h和ioctl切换到纯C。获取ESSID很简单,但是试图通过SIOCGIWSTATS获取强度/质量总是给我一个“操作不支持”的错误。有人能发现我做错了什么吗,或者可能只是我的无线驱动程序实际上不支持SIOCGIWSTATS?

请忽略全局变量的使用,在我调试当前问题时,这只是暂时的。

谢谢,

海顿。

代码语言:javascript
复制
    #include <string.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <ifaddrs.h>
    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <sys/socket.h>
    #include <linux/wireless.h>
    #include <stdlib.h>
    #include <errno.h>

    char ifname[IFNAMSIZ];
    char essid[IW_ESSID_MAX_SIZE+1];
    struct iwreq wrq;
    struct iw_statistics *iwstats;
    int sock;


    int findWifi() {
      struct ifaddrs *ifaddr, *ifa;

      if (getifaddrs(&ifaddr) == -1) {
        perror("Error getting interface addresses");
        return -1;
      }

      for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        strncpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ);

        if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
          perror("Error opening INET socket");
        }

        if (ioctl(sock, SIOCGIWNAME, &wrq) == 0) {
          printf("IF: %s\n", wrq.ifr_name);
          strcpy(ifname, wrq.ifr_name);
          freeifaddrs(ifaddr);
          return sock;
        }
      }
      freeifaddrs(ifaddr);
      return 0;
    }

    int wifiInfo() {
      wrq.u.essid.pointer = essid;
      if (ioctl(sock, SIOCGIWESSID, &wrq) == -1) {
        perror("Can't open socket to obtain essid");
        return(-1);
      }

      printf("ESSID is %s\n", wrq.u.essid.pointer);

      memset(&iwstats, 0, sizeof(iwstats));

      wrq.u.data.pointer = (caddr_t) &iwstats;
      wrq.u.data.length = sizeof(&iwstats);
      wrq.u.data.flags = 1;

      // ERROR HERE...
      if (ioctl(sock, SIOCGIWSTATS, &wrq) == -1) {
        perror("Can't open socket to obtain iwstats");
        return(-1);
      }

      return(0);
    }

    int main(int argc, char const *argv[]) {
      findWifi();
      wifiInfo();
      return 0;
    }
EN

回答 2

Stack Overflow用户

发布于 2019-11-28 19:43:38

有人能发现我做错了什么吗,或者可能只是我的无线驱动程序实际上不支持SIOCGIWSTATS?

您的代码看起来很好,或者至少非常接近,尽管这一行需要仔细检查:

代码语言:javascript
复制
wrq.u.data.pointer = (caddr_t) &iwstats;

这不能在Ubuntu16.04上编译,因为caddr_t未声明。即使在添加<linux/types.h> and <sys/types.h>之后也会发生这种情况。

谷歌一下似乎表明这个caddr_t是特定于BSD的,建议你不要使用它:

What is the significance of caddr_t and when is it used?

对于你的问题的第二部分,你可以使用像iwconfig这样的常用工具来检查Wifi驱动程序是否支持SIOCGIWSTATS

票数 1
EN

Stack Overflow用户

发布于 2019-11-28 21:54:12

感谢artm建议的iwconfig,它指出它不能作为非根用户工作。通过微小的更改,代码现在可以作为根用户工作(尽管需要一些整理,例如:删除全局变量,检查iwstats.qual.updated是否为正确的值等)。我将不得不了解为什么非root用户不能运行它,但这是另一个问题。

代码语言:javascript
复制
    #include <string.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <ifaddrs.h>
    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <sys/socket.h>
    #include <linux/wireless.h>
    #include <stdlib.h>
    #include <errno.h>

    char ifname[IFNAMSIZ];
    char essid[IW_ESSID_MAX_SIZE+1];
    struct iwreq wrq;
    struct iw_statistics iwstats;
    int sock;


    int findWifi() {
      struct ifaddrs *ifaddr, *ifa;

      if (getifaddrs(&ifaddr) == -1) {
        perror("Error getting interface addresses");
        return -1;
      }

      for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        strncpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ);

        if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
          perror("Error opening INET socket");
        }

        if (ioctl(sock, SIOCGIWNAME, &wrq) == 0) {
          printf("IF: %s\n", wrq.ifr_name);
          strcpy(ifname, wrq.ifr_name);
          freeifaddrs(ifaddr);
          return sock;
        }
      }
      freeifaddrs(ifaddr);
      return 0;
    }

    int wifiInfo() {
      wrq.u.essid.pointer = essid;
      if (ioctl(sock, SIOCGIWESSID, &wrq) == -1) {
        perror("Can't open socket to obtain essid");
        return(-1);
      }

      printf("ESSID is %s\n", wrq.u.essid.pointer);

      memset(&iwstats, 0, sizeof(iwstats));

      wrq.u.data.pointer = &iwstats;
      wrq.u.data.length = sizeof(struct iw_statistics);
      wrq.u.data.flags = 1;

      if (ioctl(sock, SIOCGIWSTATS, &wrq) == -1) {
        perror("Can't open socket to obtain iwstats");
        return(-1);
      }

      printf("Signal level is %d\n", iwstats.qual.updated);
      return(0);
    }

    int main(int argc, char const *argv[]) {
      findWifi();
      wifiInfo();
      return 0;
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59087739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档