libiwinfo: fix scan issues in nl80211, encryption detection fixes for madwifi
authorJo-Philipp Wich <jow@openwrt.org>
Sat, 4 Dec 2010 23:25:14 +0000 (23:25 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sat, 4 Dec 2010 23:25:14 +0000 (23:25 +0000)
contrib/package/iwinfo/Makefile
contrib/package/iwinfo/src/iwinfo_madwifi.c
contrib/package/iwinfo/src/iwinfo_nl80211.c

index e9edc2c..c890910 100644 (file)
@@ -7,7 +7,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=libiwinfo
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=libiwinfo
-PKG_RELEASE:=12
+PKG_RELEASE:=13
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 
index a607013..59c42db 100644 (file)
@@ -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;
 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));
        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;
 
        /* 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 )
        {
        /* 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);
        }
 
                        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;
 
        /* 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;
 
                        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;
 
                        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;
 
                        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) )
                        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:
                                        break;
 
                                default:
+                                       c->pair_ciphers = IWINFO_CIPHER_WEP40 |
+                                               IWINFO_CIPHER_WEP104;
                                        break;
                        }
                }
                                        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 )
        {
        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;
                        case IEEE80211_CIPHER_TKIP:
                                c->group_ciphers |= IWINFO_CIPHER_TKIP;
                                break;
index 4868db1..aca2be2 100644 (file)
@@ -333,18 +333,37 @@ static char * nl80211_hostapd_info(const char *ifname)
        return NULL;
 }
 
        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;
        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 };
 
        struct sockaddr_un local = { 0 };
        struct sockaddr_un remote = { 0 };
 
-       fd_set rfds;
 
        sock = socket(PF_UNIX, SOCK_DGRAM, 0);
        if( sock < 0 )
 
        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;
 
        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 )
        {
        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;
                        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;
        }
 
                        break;
        }
 
@@ -933,7 +953,7 @@ int nl80211_get_encryption(const char *ifname, char *buf)
        }
 
        /* WPA supplicant */
        }
 
        /* 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 */
                 (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 */
        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);
 
                {
                        nl80211_get_quality_max(ifname, &qmax);
 
@@ -1262,7 +1280,7 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 
                        count = 0;
 
 
                        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 */
                                      bssid, &freq, &rssi, cipher, ssid) > 0 )
                        {
                                /* BSSID */
@@ -1315,6 +1333,10 @@ int nl80211_get_scanlist(const char *ifname, char *buf, int *len)
 
                                count++;
                                e++;
 
                                count++;
                                e++;
+
+                               memset(ssid, 0, sizeof(ssid));
+                               memset(bssid, 0, sizeof(bssid));
+                               memset(cipher, 0, sizeof(cipher));
                        }
 
                        *len = count * sizeof(struct iwinfo_scanlist_entry);
                        }
 
                        *len = count * sizeof(struct iwinfo_scanlist_entry);