我目前有一个应用程序,它获得essid和信号强度使用popen(nmcli...)我正在尝试使用wireless.h和ioctl切换到纯C。获取ESSID很简单,但是试图通过SIOCGIWSTATS获取强度/质量总是给我一个“操作不支持”的错误。有人能发现我做错了什么吗,或者可能只是我的无线驱动程序实际上不支持SIOCGIWSTATS?
请忽略全局变量的使用,在我调试当前问题时,这只是暂时的。
谢谢,
海顿。
#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;
}发布于 2019-11-28 19:43:38
有人能发现我做错了什么吗,或者可能只是我的无线驱动程序实际上不支持SIOCGIWSTATS?
您的代码看起来很好,或者至少非常接近,尽管这一行需要仔细检查:
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。
发布于 2019-11-28 21:54:12
感谢artm建议的iwconfig,它指出它不能作为非根用户工作。通过微小的更改,代码现在可以作为根用户工作(尽管需要一些整理,例如:删除全局变量,检查iwstats.qual.updated是否为正确的值等)。我将不得不了解为什么非root用户不能运行它,但这是另一个问题。
#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;
}https://stackoverflow.com/questions/59087739
复制相似问题