diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2010-10-12 06:25:50 +0000 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2010-10-12 06:25:50 +0000 |
commit | 62fe7c0e77d4ebc7e21b54f4526d5ff2dad9617a (patch) | |
tree | c74e11c0f8378b59243e5d7d03e3123a70ba9445 /contrib/package/iwinfo/src/iwinfo_nl80211.c | |
parent | 551224f51cfd6976fb5671005328f1c0d43c31e6 (diff) |
libiwinfo: support scanning on radioX pseudo interfaces
Diffstat (limited to 'contrib/package/iwinfo/src/iwinfo_nl80211.c')
-rw-r--r-- | contrib/package/iwinfo/src/iwinfo_nl80211.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/contrib/package/iwinfo/src/iwinfo_nl80211.c b/contrib/package/iwinfo/src/iwinfo_nl80211.c index a693d53db7..e35dbab38a 100644 --- a/contrib/package/iwinfo/src/iwinfo_nl80211.c +++ b/contrib/package/iwinfo/src/iwinfo_nl80211.c @@ -385,6 +385,93 @@ out: return rv; } +static char * nl80211_phy2ifname(const char *ifname) +{ + int fd, phyidx = 0; + char buffer[64]; + static char nif[IFNAMSIZ] = { 0 }; + + DIR *d; + struct dirent *e; + + if( !strncmp(ifname, "radio", 5) ) + { + phyidx = atoi(&ifname[5]); + + if( (d = opendir("/sys/class/net")) != NULL ) + { + while( (e = readdir(d)) != NULL ) + { + snprintf(buffer, sizeof(buffer), + "/sys/class/net/%s/phy80211/index", e->d_name); + + if( (fd = open(buffer, O_RDONLY)) > 0 ) + { + if( (read(fd, buffer, sizeof(buffer)) > 0) && + (atoi(buffer) == phyidx) ) + { + strncpy(nif, e->d_name, sizeof(nif)); + } + + close(fd); + } + + if( nif[0] ) + break; + } + + closedir(d); + } + } + + return nif[0] ? nif : NULL; +} + +static char * nl80211_add_tempif(const char *ifname) +{ + int phyidx; + char *rv = NULL; + static char nif[IFNAMSIZ] = { 0 }; + struct nl80211_msg_conveyor *req, *res; + + req = nl80211_msg(ifname, NL80211_CMD_NEW_INTERFACE, 0); + if( req ) + { + snprintf(nif, sizeof(nif), "tmp.%s", ifname); + + NLA_PUT_STRING(req->msg, NL80211_ATTR_IFNAME, nif); + NLA_PUT_U32(req->msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_STATION); + + res = nl80211_send(req); + if( res ) + { + rv = nif; + nl80211_free(res); + } + + nla_put_failure: + nl80211_free(req); + } + + return rv; +} + +static void nl80211_del_tempif(const char *ifname) +{ + struct nl80211_msg_conveyor *req, *res; + + req = nl80211_msg(ifname, NL80211_CMD_DEL_INTERFACE, 0); + if( req ) + { + NLA_PUT_STRING(req->msg, NL80211_ATTR_IFNAME, ifname); + + nl80211_free(nl80211_send(req)); + + nla_put_failure: + nl80211_free(req); + } +} + int nl80211_probe(const char *ifname) { @@ -1058,6 +1145,24 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len) char bssid[18] = { 0 }; char cipher[256] = { 0 }; + /* Got a radioX pseudo interface, find some interface on it or create one */ + if( !strncmp(ifname, "radio", 5) ) + { + /* Reuse existing interface */ + if( (res = nl80211_phy2ifname(ifname)) != NULL ) + { + return nl80211_get_scanlist(res, buf, len); + } + + /* Need to spawn a temporary iface for scanning */ + else if( (res = nl80211_add_tempif(ifname)) != NULL ) + { + count = nl80211_get_scanlist(res, buf, len); + nl80211_del_tempif(res); + return count; + } + } + struct iwinfo_scanlist_entry *e = (struct iwinfo_scanlist_entry *)buf; /* WPA supplicant */ |