I am constantly learning new things about operating systems, and I had never heard of ioctl before. It only took a quick Google search to realize how immensely powerful it is, and how well it suited my needs. Ioctl is a means of interacting with device drivers. You pass it a request code along with a pointer to memory.
Since I don't consider the automated gathering of Wifi signal strength to be that obscure of a task, I've decided to post my solution here on my blog. I'm surprised that I was unable to find it documented elsewhere.
There are a few libraries that you need to be sure to include. I believe I have read that wireless.h may exist elsewhere on other distributions, but every machine that my code is running on uses Ubuntu so I didn't look any further in to that.
//libraries necessary for wifi ioctl communication
#include <linux/wireless.h>
#include <sys/ioctl.h>
//struct to hold collected information
struct signalInfo {
char mac[18];
char ssid[33];
int bitrate;
int level;
};
For clarity, I also have a struct that I'm using to hold all of the data I collect.
Here is the function in which the actual collection occurs. The iwname parameter is the name of the wireless network interface.
int getSignalInfo(signalInfo *sigInfo, char *iwname){
iwreq req;
strcpy(req.ifr_name, iwname);
iw_statistics *stats;
//have to use a socket for ioctl
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
//make room for the iw_statistics object
req.u.data.pointer = (iw_statistics *)malloc(sizeof(iw_statistics));
req.u.data.length = sizeof(iw_statistics);
//this will gather the signal strength
if(ioctl(sockfd, SIOCGIWSTATS, &req) == -1){
//die with error, invalid interface
fprintf(stderr, "Invalid interface.\n");
return(-1);
}
else if(((iw_statistics *)req.u.data.pointer)->qual.updated & IW_QUAL_DBM){
//signal is measured in dBm and is valid for us to use
sigInfo->level=((iw_statistics *)req.u.data.pointer)->qual.level - 256;
}
//SIOCGIWESSID for ssid
char buffer[32];
memset(buffer, 0, 32);
req.u.essid.pointer = buffer;
req.u.essid.length = 32;
//this will gather the SSID of the connected network
if(ioctl(sockfd, SIOCGIWESSID, &req) == -1){
//die with error, invalid interface
return(-1);
}
else{
memcpy(&sigInfo->ssid, req.u.essid.pointer, req.u.essid.length);
memset(&sigInfo->ssid[req.u.essid.length],0,1);
}
//SIOCGIWRATE for bits/sec (convert to mbit)
int bitrate=-1;
//this will get the bitrate of the link
if(ioctl(sockfd, SIOCGIWRATE, &req) == -1){
fprintf(stderr, "bitratefail");
return(-1);
}else{
memcpy(&bitrate, &req.u.bitrate, sizeof(int));
sigInfo->bitrate=bitrate/1000000;
}
//SIOCGIFHWADDR for mac addr
ifreq req2;
strcpy(req2.ifr_name, iwname);
//this will get the mac address of the interface
if(ioctl(sockfd, SIOCGIFHWADDR, &req2) == -1){
fprintf(stderr, "mac error");
return(-1);
}
else{
sprintf(sigInfo->mac, "%.2X", (unsigned char)req2.ifr_hwaddr.sa_data[0]);
for(int s=1; s<6; s++){
sprintf(sigInfo->mac+strlen(sigInfo->mac), ":%.2X", (unsigned char)req2.ifr_hwaddr.sa_data[s]);
}
}
close(sockfd);
}
This seems to work very reliably for me. Hopefully it will save some poor soul from having to parse iwconfig in the future. Happy programming!
Sir I m totally new to this field
ReplyDeletekindly guide me how can I get Received Signal Strength from the wifi interface every time it receives a packett/frame
I'll be really grateful
thank you n waiting for your rply
Haroon,
DeleteSorry for the late reply. Unfortunately, I am not sure how to do that. The only way I would know how to do that is by polling ioctl (like I did above) after a socket recv(). I do not think that is an efficient way, and I am sure there is a better way to do it. Unfortunately, I am not that familiar with capturing system events from UNIX. Sorry that I could not be of more help!
Adam
Line 5 should be : struct iw_statistics *stats;
ReplyDeleteline 11~12 should be:
ReplyDeletereq.u.data.pointer = (struct iw_statistics *) malloc(sizeof(* stats));
req.u.data.length = sizeof(* stats);
req.u.data.flags = 1;
invalid interface i am getting.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDelete