From 8c9acb01f4e345a096042a994e1655b21689a3cf Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sat, 4 Dec 2010 23:25:14 +0000 Subject: [PATCH] libiwinfo: fix scan issues in nl80211, encryption detection fixes for madwifi --- contrib/package/iwinfo/Makefile | 2 +- contrib/package/iwinfo/src/iwinfo_madwifi.c | 36 +++++++---- contrib/package/iwinfo/src/iwinfo_nl80211.c | 68 ++++++++++++++------- 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/contrib/package/iwinfo/Makefile b/contrib/package/iwinfo/Makefile index e9edc2ccc..c89091003 100644 --- a/contrib/package/iwinfo/Makefile +++ b/contrib/package/iwinfo/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libiwinfo -PKG_RELEASE:=12 +PKG_RELEASE:=13 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) diff --git a/contrib/package/iwinfo/src/iwinfo_madwifi.c b/contrib/package/iwinfo/src/iwinfo_madwifi.c index a6070132b..59c42dbc9 100644 --- a/contrib/package/iwinfo/src/iwinfo_madwifi.c +++ b/contrib/package/iwinfo/src/iwinfo_madwifi.c @@ -549,13 +549,23 @@ int madwifi_get_quality_max(const char *ifname, int *buf) int madwifi_get_encryption(const char *ifname, char *buf) { int ciphers = 0, key_len = 0; + char keybuf[IW_ENCODING_TOKEN_MAX]; struct iwinfo_crypto_entry *c = (struct iwinfo_crypto_entry *)buf; struct iwreq wrq; struct ieee80211req_key wk; memset(&wrq, 0, sizeof(wrq)); - memset(&wk, 0, sizeof(wk)); - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); + + /* Obtain key info */ + if( madwifi_wrq(&wrq, ifname, SIOCGIWENCODE, keybuf, sizeof(keybuf)) < 0 ) + return -1; + + /* Have any encryption? */ + if( (wrq.u.data.flags & IW_ENCODE_DISABLED) || (wrq.u.data.length == 0) ) + return 0; + + /* Save key len */ + key_len = wrq.u.data.length; /* Get wpa protocol version */ wrq.u.mode = IEEE80211_PARAM_WPA; @@ -589,6 +599,9 @@ int madwifi_get_encryption(const char *ifname, char *buf) } } + memset(&wk, 0, sizeof(wk)); + memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); + /* Get key information */ if( get80211priv(ifname, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk)) >= 0 ) { @@ -597,27 +610,22 @@ int madwifi_get_encryption(const char *ifname, char *buf) c->auth_algs = (IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED); } - /* Get group key length */ - wrq.u.mode = IEEE80211_PARAM_MCASTKEYLEN; - if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) - key_len = wrq.u.mode; - /* Get used pairwise ciphers */ wrq.u.mode = IEEE80211_PARAM_UCASTCIPHERS; if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) { ciphers = wrq.u.mode; - if( ciphers & (1 << IEEE80211_CIPHER_TKIP) ) + if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_TKIP) ) c->pair_ciphers |= IWINFO_CIPHER_TKIP; - if( ciphers & (1 << IEEE80211_CIPHER_AES_CCM) ) + if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_AES_CCM) ) c->pair_ciphers |= IWINFO_CIPHER_CCMP; - if( ciphers & (1 << IEEE80211_CIPHER_AES_OCB) ) + if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_AES_OCB) ) c->pair_ciphers |= IWINFO_CIPHER_AESOCB; - if( ciphers & (1 << IEEE80211_CIPHER_CKIP) ) + if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_CKIP) ) c->pair_ciphers |= IWINFO_CIPHER_CKIP; if( ciphers & (1 << IEEE80211_CIPHER_WEP) ) @@ -632,6 +640,8 @@ int madwifi_get_encryption(const char *ifname, char *buf) break; default: + c->pair_ciphers = IWINFO_CIPHER_WEP40 | + IWINFO_CIPHER_WEP104; break; } } @@ -644,9 +654,9 @@ int madwifi_get_encryption(const char *ifname, char *buf) wrq.u.mode = IEEE80211_PARAM_MCASTCIPHER; if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) { - ciphers = wrq.u.mode; + ciphers = c->wpa_version ? wrq.u.mode : IEEE80211_CIPHER_WEP; - switch(wrq.u.mode) { + switch(ciphers) { case IEEE80211_CIPHER_TKIP: c->group_ciphers |= IWINFO_CIPHER_TKIP; break; diff --git a/contrib/package/iwinfo/src/iwinfo_nl80211.c b/contrib/package/iwinfo/src/iwinfo_nl80211.c index 4868db10e..aca2be233 100644 --- a/contrib/package/iwinfo/src/iwinfo_nl80211.c +++ b/contrib/package/iwinfo/src/iwinfo_nl80211.c @@ -333,18 +333,37 @@ static char * nl80211_hostapd_info(const char *ifname) return NULL; } -static char * nl80211_wpasupp_info(const char *ifname, const char *cmd) +static inline int nl80211_wpactl_recv(int sock, char *buf, int blen) { - int sock = -1, len; + fd_set rfds; + struct timeval tv = { 2, 0 }; + + FD_ZERO(&rfds); + FD_SET(sock, &rfds); + + memset(buf, 0, blen); + + + if( select(sock + 1, &rfds, NULL, NULL, &tv) < 0 ) + return -1; + + if( !FD_ISSET(sock, &rfds) ) + return -1; + + return recv(sock, buf, blen, 0); +} + +static char * nl80211_wpactl_info(const char *ifname, const char *cmd, + const char *event) +{ + int sock = -1; char *rv = NULL; size_t remote_length, local_length; - static char buffer[1024] = { 0 }; + static char buffer[10240] = { 0 }; - struct timeval tv = { 2, 0 }; struct sockaddr_un local = { 0 }; struct sockaddr_un remote = { 0 }; - fd_set rfds; sock = socket(PF_UNIX, SOCK_DGRAM, 0); if( sock < 0 ) @@ -367,25 +386,26 @@ static char * nl80211_wpasupp_info(const char *ifname, const char *cmd) if( bind(sock, (struct sockaddr *) &local, local_length) ) goto out; + + send(sock, "ATTACH", 6, 0); + + if( nl80211_wpactl_recv(sock, buffer, sizeof(buffer)) <= 0 ) + goto out; + + send(sock, cmd, strlen(cmd), 0); while( 1 ) { - FD_ZERO(&rfds); - FD_SET(sock, &rfds); - - if( select(sock + 1, &rfds, NULL, NULL, &tv) < 0 ) - goto out; + if( nl80211_wpactl_recv(sock, buffer, sizeof(buffer)) <= 0 ) + { + if( event ) + continue; - if( !FD_ISSET(sock, &rfds) ) break; + } - if( (len = recv(sock, buffer, sizeof(buffer), 0)) <= 0 ) - goto out; - - buffer[len] = 0; - - if( buffer[0] != '<' ) + if( (!event && buffer[0] != '<') || strstr(buffer, event) ) break; } @@ -933,7 +953,7 @@ int nl80211_get_encryption(const char *ifname, char *buf) } /* WPA supplicant */ - else if( (res = nl80211_wpasupp_info(ifname, "STATUS")) && + else if( (res = nl80211_wpactl_info(ifname, "STATUS", NULL)) && (val = nl80211_getval(NULL, res, "pairwise_cipher")) ) { /* WEP */ @@ -1249,11 +1269,9 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len) struct iwinfo_scanlist_entry *e = (struct iwinfo_scanlist_entry *)buf; /* WPA supplicant */ - if( (res = nl80211_wpasupp_info(ifname, "SCAN")) && !strcmp(res, "OK\n") ) + if( (res = nl80211_wpactl_info(ifname, "SCAN", "CTRL-EVENT-SCAN-RESULTS")) ) { - sleep(2); - - if( (res = nl80211_wpasupp_info(ifname, "SCAN_RESULTS")) ) + if( (res = nl80211_wpactl_info(ifname, "SCAN_RESULTS", NULL)) ) { nl80211_get_quality_max(ifname, &qmax); @@ -1262,7 +1280,7 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len) count = 0; - while( sscanf(res, "%17s %d %d %255s %127[^\n]\n", + while( sscanf(res, "%17s %d %d %255s%*[ \t]%127[^\n]\n", bssid, &freq, &rssi, cipher, ssid) > 0 ) { /* BSSID */ @@ -1315,6 +1333,10 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len) count++; e++; + + memset(ssid, 0, sizeof(ssid)); + memset(bssid, 0, sizeof(bssid)); + memset(cipher, 0, sizeof(cipher)); } *len = count * sizeof(struct iwinfo_scanlist_entry); -- 2.25.1