libiwinfo: do survey without bringing down the ap if possible
This commit is contained in:
parent
ed2a631f4d
commit
b18db85cd2
2 changed files with 127 additions and 51 deletions
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
extern struct iwinfo_iso3166_label ISO3166_Names[];
|
extern struct iwinfo_iso3166_label ISO3166_Names[];
|
||||||
static struct nl80211_state *nls = NULL;
|
static struct nl80211_state *nls = NULL;
|
||||||
|
static int nl80211_ioctlsock = -1;
|
||||||
|
|
||||||
static int nl80211_init(void)
|
static int nl80211_init(void)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +37,19 @@ static int nl80211_init(void)
|
||||||
|
|
||||||
if( !nls )
|
if( !nls )
|
||||||
{
|
{
|
||||||
|
nl80211_ioctlsock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if( nl80211_ioctlsock < 0 )
|
||||||
|
{
|
||||||
|
err = -ENOLINK;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
else if( fcntl(nl80211_ioctlsock, F_SETFD,
|
||||||
|
fcntl(nl80211_ioctlsock, F_GETFD) | FD_CLOEXEC) < 0 )
|
||||||
|
{
|
||||||
|
err = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
nls = malloc(sizeof(struct nl80211_state));
|
nls = malloc(sizeof(struct nl80211_state));
|
||||||
if( !nls ) {
|
if( !nls ) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
@ -391,6 +405,8 @@ static char * nl80211_wpasupp_info(const char *ifname, const char *cmd)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
close(sock);
|
close(sock);
|
||||||
|
|
||||||
|
if( local.sun_family )
|
||||||
unlink(local.sun_path);
|
unlink(local.sun_path);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -438,7 +454,7 @@ static char * nl80211_phy2ifname(const char *ifname)
|
||||||
return nif[0] ? nif : NULL;
|
return nif[0] ? nif : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char * nl80211_add_tempif(const char *ifname)
|
static char * nl80211_ifadd(const char *ifname)
|
||||||
{
|
{
|
||||||
int phyidx;
|
int phyidx;
|
||||||
char *rv = NULL;
|
char *rv = NULL;
|
||||||
|
@ -467,7 +483,7 @@ static char * nl80211_add_tempif(const char *ifname)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nl80211_del_tempif(const char *ifname)
|
static void nl80211_ifdel(const char *ifname)
|
||||||
{
|
{
|
||||||
struct nl80211_msg_conveyor *req, *res;
|
struct nl80211_msg_conveyor *req, *res;
|
||||||
|
|
||||||
|
@ -483,6 +499,71 @@ static void nl80211_del_tempif(const char *ifname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nl80211_ifup(const char *ifname)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||||
|
|
||||||
|
if( ioctl(nl80211_ioctlsock, SIOCGIFFLAGS, &ifr) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
|
||||||
|
|
||||||
|
return !ioctl(nl80211_ioctlsock, SIOCSIFFLAGS, &ifr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_ifdown(const char *ifname)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||||
|
|
||||||
|
if( ioctl(nl80211_ioctlsock, SIOCGIFFLAGS, &ifr) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
|
||||||
|
|
||||||
|
return !ioctl(nl80211_ioctlsock, SIOCSIFFLAGS, &ifr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl80211_ifmac(const char *ifname)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
|
||||||
|
|
||||||
|
if( ioctl(nl80211_ioctlsock, SIOCGIFHWADDR, &ifr) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ifr.ifr_hwaddr.sa_data[1]++;
|
||||||
|
ifr.ifr_hwaddr.sa_data[2]++;
|
||||||
|
|
||||||
|
return !ioctl(nl80211_ioctlsock, SIOCSIFHWADDR, &ifr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl80211_hostapd_hup(const char *ifname)
|
||||||
|
{
|
||||||
|
int fd, pid = 0;
|
||||||
|
char buf[32];
|
||||||
|
char *phy = strncmp(ifname, "phy", 3) ? nl80211_ifname2phy(ifname) : ifname;
|
||||||
|
|
||||||
|
if( phy )
|
||||||
|
{
|
||||||
|
snprintf(buf, sizeof(buf), "/var/run/wifi-%s.pid", phy);
|
||||||
|
if( (fd = open(buf, O_RDONLY)) > 0 )
|
||||||
|
{
|
||||||
|
if( read(fd, buf, sizeof(buf)) > 0 )
|
||||||
|
pid = atoi(buf);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pid > 0 )
|
||||||
|
kill(pid, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int nl80211_probe(const char *ifname)
|
int nl80211_probe(const char *ifname)
|
||||||
{
|
{
|
||||||
|
@ -491,6 +572,11 @@ int nl80211_probe(const char *ifname)
|
||||||
|
|
||||||
void nl80211_close(void)
|
void nl80211_close(void)
|
||||||
{
|
{
|
||||||
|
if( nl80211_ioctlsock > -1 )
|
||||||
|
{
|
||||||
|
close(nl80211_ioctlsock);
|
||||||
|
}
|
||||||
|
|
||||||
if( nls )
|
if( nls )
|
||||||
{
|
{
|
||||||
if( nls->nl_sock )
|
if( nls->nl_sock )
|
||||||
|
@ -1150,7 +1236,6 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
|
||||||
{
|
{
|
||||||
int freq, rssi, qmax, count;
|
int freq, rssi, qmax, count;
|
||||||
char *res;
|
char *res;
|
||||||
char cmd[256];
|
|
||||||
char ssid[128] = { 0 };
|
char ssid[128] = { 0 };
|
||||||
char bssid[18] = { 0 };
|
char bssid[18] = { 0 };
|
||||||
char cipher[256] = { 0 };
|
char cipher[256] = { 0 };
|
||||||
|
@ -1165,10 +1250,10 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need to spawn a temporary iface for scanning */
|
/* Need to spawn a temporary iface for scanning */
|
||||||
else if( (res = nl80211_add_tempif(ifname)) != NULL )
|
else if( (res = nl80211_ifadd(ifname)) != NULL )
|
||||||
{
|
{
|
||||||
count = nl80211_get_scanlist(res, buf, len);
|
count = nl80211_get_scanlist(res, buf, len);
|
||||||
nl80211_del_tempif(res);
|
nl80211_ifdel(res);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1252,60 +1337,50 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
|
||||||
|
|
||||||
/* AP scan */
|
/* AP scan */
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if( (res = nl80211_ifname2phy(ifname)) != NULL )
|
|
||||||
{
|
{
|
||||||
/* Got a temp interface, don't create yet another one */
|
/* Got a temp interface, don't create yet another one */
|
||||||
if( !strncmp(ifname, "tmp.", 4) )
|
if( !strncmp(ifname, "tmp.", 4) )
|
||||||
{
|
{
|
||||||
sprintf(cmd, "ifconfig %s up 2>/dev/null", ifname);
|
if( !nl80211_ifup(ifname) )
|
||||||
if( WEXITSTATUS(system(cmd)) )
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wext_get_scanlist(ifname, buf, len);
|
wext_get_scanlist(ifname, buf, len);
|
||||||
|
nl80211_ifdown(ifname);
|
||||||
sprintf(cmd, "ifconfig %s down 2>/dev/null", ifname);
|
|
||||||
(void) WEXITSTATUS(system(cmd));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spawn a new scan interface */
|
/* Spawn a new scan interface */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(cmd, "ifconfig %s down 2>/dev/null", ifname);
|
if( !(res = nl80211_ifadd(ifname)) )
|
||||||
if( WEXITSTATUS(system(cmd)) )
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
sprintf(cmd, "iw phy %s interface add scan.%s "
|
if( !nl80211_ifmac(res) )
|
||||||
"type station 2>/dev/null", res, ifname);
|
|
||||||
if( WEXITSTATUS(system(cmd)) )
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
sprintf(cmd, "ifconfig scan.%s up 2>/dev/null", ifname);
|
/* if we can take the new interface up, the driver supports an
|
||||||
if( WEXITSTATUS(system(cmd)) )
|
* additional interface and there's no need to tear down the ap */
|
||||||
goto out;
|
if( nl80211_ifup(res) )
|
||||||
|
{
|
||||||
|
wext_get_scanlist(res, buf, len);
|
||||||
|
nl80211_ifdown(res);
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(cmd, "scan.%s", ifname);
|
/* driver cannot create secondary interface, take down ap
|
||||||
wext_get_scanlist(cmd, buf, len);
|
* during scan */
|
||||||
|
else if( nl80211_ifdown(ifname) && nl80211_ifup(res) )
|
||||||
|
{
|
||||||
|
wext_get_scanlist(res, buf, len);
|
||||||
|
nl80211_ifdown(res);
|
||||||
|
nl80211_ifup(ifname);
|
||||||
|
nl80211_hostapd_hup(ifname);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
sprintf(cmd, "ifconfig scan.%s down 2>/dev/null", ifname);
|
nl80211_ifdel(res);
|
||||||
(void) WEXITSTATUS(system(cmd));
|
|
||||||
|
|
||||||
sprintf(cmd, "iw dev scan.%s del 2>/dev/null", ifname);
|
|
||||||
(void) WEXITSTATUS(system(cmd));
|
|
||||||
|
|
||||||
sprintf(cmd, "ifconfig %s up 2>/dev/null", ifname);
|
|
||||||
(void) WEXITSTATUS(system(cmd));
|
|
||||||
|
|
||||||
sprintf(cmd, "killall -HUP hostapd 2>/dev/null");
|
|
||||||
(void) WEXITSTATUS(system(cmd));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
|
Loading…
Reference in a new issue