Changeset 30691


Ignore:
Timestamp:
2012-02-23T13:18:46+01:00 (6 years ago)
Author:
jow
Message:

[package] iwinfo: implement netlink scanning code, rework IE parsing code

Location:
trunk/package/iwinfo
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/iwinfo/Makefile

    r30682 r30691  
    88 
    99PKG_NAME:=libiwinfo 
    10 PKG_RELEASE:=29 
     10PKG_RELEASE:=30 
    1111 
    1212PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) 
  • trunk/package/iwinfo/src/include/iwinfo/nl80211.h

    r29425 r30691  
    4040        struct nl_cache *nl_cache; 
    4141        struct genl_family *nl80211; 
     42        struct genl_family *nlctrl; 
    4243}; 
    4344 
     
    4546        struct nl_msg *msg; 
    4647        struct nl_cb *cb; 
     48}; 
     49 
     50struct nl80211_event_conveyor { 
     51        int wait; 
     52        int recv; 
     53}; 
     54 
     55struct nl80211_group_conveyor { 
     56        const char *name; 
     57        int id; 
    4758}; 
    4859 
  • trunk/package/iwinfo/src/include/iwinfo/utils.h

    r30605 r30691  
    4242int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id); 
    4343 
     44void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len, 
     45                                          uint8_t defcipher, uint8_t defauth); 
     46 
    4447#endif 
  • trunk/package/iwinfo/src/iwinfo_cli.c

    r30682 r30691  
    231231                                        snprintf(buf, sizeof(buf), "mixed WPA/WPA2 %s (%s)", 
    232232                                                format_enc_suites(c->auth_suites), 
    233                                                 format_enc_ciphers(c->pair_ciphers & c->group_ciphers)); 
     233                                                format_enc_ciphers(c->pair_ciphers | c->group_ciphers)); 
    234234                                        break; 
    235235 
     
    237237                                        snprintf(buf, sizeof(buf), "WPA2 %s (%s)", 
    238238                                                format_enc_suites(c->auth_suites), 
    239                                                 format_enc_ciphers(c->pair_ciphers & c->group_ciphers)); 
     239                                                format_enc_ciphers(c->pair_ciphers | c->group_ciphers)); 
    240240                                        break; 
    241241 
     
    243243                                        snprintf(buf, sizeof(buf), "WPA %s (%s)", 
    244244                                                format_enc_suites(c->auth_suites), 
    245                                                 format_enc_ciphers(c->pair_ciphers & c->group_ciphers)); 
     245                                                format_enc_ciphers(c->pair_ciphers | c->group_ciphers)); 
    246246                                        break; 
    247247                        } 
  • trunk/package/iwinfo/src/iwinfo_nl80211.c

    r30682 r30691  
    4848                } 
    4949 
    50                 if( genl_connect(nls->nl_sock)) { 
     50                if (genl_connect(nls->nl_sock)) { 
    5151                        err = -ENOLINK; 
    5252                        goto err; 
     
    5454 
    5555                fd = nl_socket_get_fd(nls->nl_sock); 
    56                 if (fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) < 0) 
    57                 { 
     56                if (fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) < 0) { 
    5857                        err = -EINVAL; 
    5958                        goto err; 
    6059                } 
    6160 
    62                 if( genl_ctrl_alloc_cache(nls->nl_sock, &nls->nl_cache)) { 
     61                if (genl_ctrl_alloc_cache(nls->nl_sock, &nls->nl_cache)) { 
    6362                        err = -ENOMEM; 
    6463                        goto err; 
     
    6665 
    6766                nls->nl80211 = genl_ctrl_search_by_name(nls->nl_cache, "nl80211"); 
    68                 if (!nls->nl80211) 
    69                 { 
     67                if (!nls->nl80211) { 
     68                        err = -ENOENT; 
     69                        goto err; 
     70                } 
     71 
     72                nls->nlctrl = genl_ctrl_search_by_name(nls->nl_cache, "nlctrl"); 
     73                if (!nls->nlctrl) { 
    7074                        err = -ENOENT; 
    7175                        goto err; 
     
    8185} 
    8286 
     87 
    8388static int nl80211_msg_error(struct sockaddr_nl *nla, 
    8489        struct nlmsgerr *err, void *arg) 
     
    123128} 
    124129 
    125 static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, int cmd, int flags) 
     130static struct nl80211_msg_conveyor * nl80211_new(struct genl_family *family, 
     131                                                 int cmd, int flags) 
    126132{ 
    127133        static struct nl80211_msg_conveyor cv; 
    128134 
    129         int ifidx = -1, phyidx = -1; 
    130135        struct nl_msg *req = NULL; 
    131136        struct nl_cb *cb = NULL; 
    132137 
     138        req = nlmsg_alloc(); 
     139        if (!req) 
     140                goto err; 
     141 
     142        cb = nl_cb_alloc(NL_CB_DEFAULT); 
     143        if (!cb) 
     144                goto err; 
     145 
     146        genlmsg_put(req, 0, 0, genl_family_get_id(family), 0, flags, cmd, 0); 
     147 
     148        cv.msg = req; 
     149        cv.cb  = cb; 
     150 
     151        return &cv; 
     152 
     153err: 
     154nla_put_failure: 
     155        if (cb) 
     156                nl_cb_put(cb); 
     157 
     158        if (req) 
     159                nlmsg_free(req); 
     160 
     161        return NULL; 
     162} 
     163 
     164static struct nl80211_msg_conveyor * nl80211_ctl(int cmd, int flags) 
     165{ 
    133166        if (nl80211_init() < 0) 
    134                 goto err; 
     167                return NULL; 
     168 
     169        return nl80211_new(nls->nlctrl, cmd, flags); 
     170} 
     171 
     172static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, 
     173                                                 int cmd, int flags) 
     174{ 
     175        int ifidx = -1, phyidx = -1; 
     176        struct nl80211_msg_conveyor *cv; 
     177 
     178        if (nl80211_init() < 0) 
     179                return NULL; 
    135180 
    136181        if (!strncmp(ifname, "phy", 3)) 
     
    146191                return NULL; 
    147192 
    148         req = nlmsg_alloc(); 
    149         if (!req) 
    150                 goto err; 
    151  
    152         cb = nl_cb_alloc(NL_CB_DEFAULT); 
    153         if (!cb) 
    154                 goto err; 
    155  
    156         genlmsg_put(req, 0, 0, genl_family_get_id(nls->nl80211), 0, 
    157                 flags, cmd, 0); 
     193        cv = nl80211_new(nls->nl80211, cmd, flags); 
     194        if (!cv) 
     195                return NULL; 
    158196 
    159197        if (ifidx > -1) 
    160                 NLA_PUT_U32(req, NL80211_ATTR_IFINDEX, ifidx); 
     198                NLA_PUT_U32(cv->msg, NL80211_ATTR_IFINDEX, ifidx); 
    161199 
    162200        if (phyidx > -1) 
    163                 NLA_PUT_U32(req, NL80211_ATTR_WIPHY, phyidx); 
    164  
    165         cv.msg = req; 
    166         cv.cb  = cb; 
    167  
    168         return &cv; 
    169  
    170 err: 
     201                NLA_PUT_U32(cv->msg, NL80211_ATTR_WIPHY, phyidx); 
     202 
     203        return cv; 
     204 
    171205nla_put_failure: 
    172         if (cb) 
    173                 nl_cb_put(cb); 
    174  
    175         if (req) 
    176                 nlmsg_free(req); 
    177  
     206        nl80211_free(cv); 
    178207        return NULL; 
    179208} 
     
    216245 
    217246        nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 
    218                 genlmsg_attrlen(gnlh, 0), NULL); 
     247                  genlmsg_attrlen(gnlh, 0), NULL); 
    219248 
    220249        return attr; 
    221250} 
    222251 
     252 
     253static int nl80211_subscribe_cb(struct nl_msg *msg, void *arg) 
     254{ 
     255        struct nl80211_group_conveyor *cv = arg; 
     256 
     257        struct nlattr **attr = nl80211_parse(msg); 
     258        struct nlattr *mgrpinfo[CTRL_ATTR_MCAST_GRP_MAX + 1]; 
     259        struct nlattr *mgrp; 
     260        int mgrpidx; 
     261 
     262        if (!attr[CTRL_ATTR_MCAST_GROUPS]) 
     263                return NL_SKIP; 
     264 
     265        nla_for_each_nested(mgrp, attr[CTRL_ATTR_MCAST_GROUPS], mgrpidx) 
     266        { 
     267                nla_parse(mgrpinfo, CTRL_ATTR_MCAST_GRP_MAX, 
     268                          nla_data(mgrp), nla_len(mgrp), NULL); 
     269 
     270                if (mgrpinfo[CTRL_ATTR_MCAST_GRP_ID] && 
     271                    mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME] && 
     272                    !strncmp(nla_data(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME]), 
     273                             cv->name, nla_len(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME]))) 
     274                { 
     275                        cv->id = nla_get_u32(mgrpinfo[CTRL_ATTR_MCAST_GRP_ID]); 
     276                        break; 
     277                } 
     278        } 
     279 
     280        return NL_SKIP; 
     281} 
     282 
     283static int nl80211_subscribe(const char *family, const char *group) 
     284{ 
     285        struct nl80211_group_conveyor cv = { .name = group, .id = -ENOENT }; 
     286        struct nl80211_msg_conveyor *req; 
     287 
     288        req = nl80211_ctl(CTRL_CMD_GETFAMILY, 0); 
     289        if (req) 
     290        { 
     291                NLA_PUT_STRING(req->msg, CTRL_ATTR_FAMILY_NAME, family); 
     292                nl80211_send(req, nl80211_subscribe_cb, &cv); 
     293 
     294nla_put_failure: 
     295                nl80211_free(req); 
     296        } 
     297 
     298        return nl_socket_add_membership(nls->nl_sock, cv.id); 
     299} 
     300 
     301 
     302static int nl80211_wait_cb(struct nl_msg *msg, void *arg) 
     303{ 
     304        struct nl80211_event_conveyor *cv = arg; 
     305        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 
     306 
     307        if (gnlh->cmd == cv->wait) 
     308                cv->recv = gnlh->cmd; 
     309 
     310        return NL_SKIP; 
     311} 
     312 
     313static int nl80211_wait_seq_check(struct nl_msg *msg, void *arg) 
     314{ 
     315        return NL_OK; 
     316} 
     317 
     318static int nl80211_wait(const char *family, const char *group, int cmd) 
     319{ 
     320        struct nl80211_event_conveyor cv = { .wait = cmd }; 
     321        struct nl_cb *cb; 
     322 
     323        if (nl80211_subscribe(family, group)) 
     324                return -ENOENT; 
     325 
     326        cb = nl_cb_alloc(NL_CB_DEFAULT); 
     327 
     328        if (!cb) 
     329                return -ENOMEM; 
     330 
     331        nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nl80211_wait_seq_check, NULL); 
     332        nl_cb_set(cb, NL_CB_VALID,     NL_CB_CUSTOM, nl80211_wait_cb,        &cv ); 
     333 
     334        while (!cv.recv) 
     335                nl_recvmsgs(nls->nl_sock, cb); 
     336 
     337        nl_cb_put(cb); 
     338 
     339        return 0; 
     340} 
     341 
     342 
    223343static int nl80211_freq2channel(int freq) 
    224344{ 
    225     if (freq == 2484) 
    226         return 14; 
    227  
    228     if (freq < 2484) 
    229         return (freq - 2407) / 5; 
    230  
    231     return (freq / 5) - 1000; 
     345        if (freq == 2484) 
     346                return 14; 
     347 
     348        if (freq < 2484) 
     349                return (freq - 2407) / 5; 
     350 
     351        return (freq / 5) - 1000; 
    232352} 
    233353 
     
    286406 
    287407        if (attr[NL80211_ATTR_WIPHY_NAME]) 
    288                 sprintf(buf, "%s", nla_data(attr[NL80211_ATTR_WIPHY_NAME])); 
     408                memcpy(buf, nla_data(attr[NL80211_ATTR_WIPHY_NAME]), 
     409                       nla_len(attr[NL80211_ATTR_WIPHY_NAME])); 
    289410        else 
    290411                buf[0] = 0; 
     
    381502 
    382503        local.sun_family = AF_UNIX; 
    383         local_length = sizeof(local.sun_family) + sprintf(local.sun_path, 
    384                 "/var/run/iwinfo-%s-%d", ifname, getpid()); 
     504        local_length = sizeof(local.sun_family) + 
     505                sprintf(local.sun_path, "/var/run/iwinfo-%s-%d", ifname, getpid()); 
    385506 
    386507        if (bind(sock, (struct sockaddr *) &local, local_length)) 
     
    463584                if ((d = opendir("/sys/class/net")) != NULL) 
    464585                { 
    465                         while( (e = readdir(d)) != NULL ) 
     586                        while ((e = readdir(d)) != NULL) 
    466587                        { 
    467588                                snprintf(buffer, sizeof(buffer), 
    468                                         "/sys/class/net/%s/phy80211/index", e->d_name); 
     589                                         "/sys/class/net/%s/phy80211/index", e->d_name); 
    469590 
    470591                                if (nl80211_readint(buffer) == phyidx) 
    471592                                { 
    472593                                        snprintf(buffer, sizeof(buffer), 
    473                                                 "/sys/class/net/%s/ifindex", e->d_name); 
    474  
    475                                         if( (cifidx = nl80211_readint(buffer)) >= 0 && 
    476                                             ((ifidx < 0) || (cifidx < ifidx)) ) 
     594                                                 "/sys/class/net/%s/ifindex", e->d_name); 
     595 
     596                                        if ((cifidx = nl80211_readint(buffer)) >= 0 && 
     597                                            ((ifidx < 0) || (cifidx < ifidx))) 
    477598                                        { 
    478599                                                ifidx = cifidx; 
     
    563684        if (nls) 
    564685        { 
     686                if (nls->nlctrl) 
     687                        genl_family_put(nls->nlctrl); 
     688 
    565689                if (nls->nl80211) 
    566690                        genl_family_put(nls->nl80211); 
     
    590714                return 0; 
    591715        } 
    592         else if( (ssid = nl80211_hostapd_info(ifname)) && 
    593                  (ssid = nl80211_getval(ifname, ssid, "ssid")) ) 
     716        else if ((ssid = nl80211_hostapd_info(ifname)) && 
     717                 (ssid = nl80211_getval(ifname, ssid, "ssid"))) 
    594718        { 
    595719                memcpy(buf, ssid, strlen(ssid)); 
     
    609733                return 0; 
    610734        } 
    611         else if((bssid = nl80211_hostapd_info(ifname)) && 
     735        else if ((bssid = nl80211_hostapd_info(ifname)) && 
    612736                 (bssid = nl80211_getval(ifname, bssid, "bssid"))) 
    613737        { 
     
    620744 
    621745                sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", 
    622                         mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 
     746                        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 
    623747 
    624748                return 0; 
     
    691815        if (attr[NL80211_ATTR_STA_INFO]) 
    692816        { 
    693                 if( !nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, 
    694                                 attr[NL80211_ATTR_STA_INFO], stats_policy) ) 
     817                if (!nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, 
     818                                      attr[NL80211_ATTR_STA_INFO], stats_policy)) 
    695819                { 
    696820                        if (sinfo[NL80211_STA_INFO_SIGNAL]) 
     
    702826                        if (sinfo[NL80211_STA_INFO_TX_BITRATE]) 
    703827                        { 
    704                                 if( !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 
    705                                                 sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy) ) 
     828                                if (!nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 
     829                                                      sinfo[NL80211_STA_INFO_TX_BITRATE], 
     830                                                      rate_policy)) 
    706831                                { 
    707832                                        if (rinfo[NL80211_RATE_INFO_BITRATE]) 
     
    733858                { 
    734859                        if (!strncmp(de->d_name, ifname, strlen(ifname)) && 
    735                                 (!de->d_name[strlen(ifname)] || 
    736                                 !strncmp(&de->d_name[strlen(ifname)], ".sta", 4))) 
     860                            (!de->d_name[strlen(ifname)] || 
     861                            !strncmp(&de->d_name[strlen(ifname)], ".sta", 4))) 
    737862                        { 
    738863                                req = nl80211_msg(de->d_name, NL80211_CMD_GET_STATION, 
    739                                                                   NLM_F_DUMP); 
     864                                                  NLM_F_DUMP); 
    740865 
    741866                                if (req) 
     
    802927 
    803928        if (nla_parse_nested(si, NL80211_SURVEY_INFO_MAX, 
    804                                                 tb[NL80211_ATTR_SURVEY_INFO], sp)) 
     929                            tb[NL80211_ATTR_SURVEY_INFO], sp)) 
    805930                return NL_SKIP; 
    806931 
     
    8911016 
    8921017        /* WPA supplicant */ 
    893         if( (res = nl80211_wpactl_info(ifname, "STATUS", NULL)) && 
    894             (val = nl80211_getval(NULL, res, "pairwise_cipher")) ) 
     1018        if ((res = nl80211_wpactl_info(ifname, "STATUS", NULL)) && 
     1019            (val = nl80211_getval(NULL, res, "pairwise_cipher"))) 
    8951020        { 
    8961021                /* WEP */ 
     
    10221147                        } 
    10231148 
    1024                         for( i = 0; i < 4; i++ ) 
     1149                        for (i = 0; i < 4; i++) 
    10251150                        { 
    10261151                                snprintf(k, sizeof(k), "wep_key%d", i); 
     
    10791204 
    10801205        if (attr[NL80211_ATTR_STA_INFO] && 
    1081                 !nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, 
    1082                         attr[NL80211_ATTR_STA_INFO], stats_policy)) 
     1206            !nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, 
     1207                              attr[NL80211_ATTR_STA_INFO], stats_policy)) 
    10831208        { 
    10841209                if (sinfo[NL80211_STA_INFO_SIGNAL]) 
     
    10951220 
    10961221                if (sinfo[NL80211_STA_INFO_RX_BITRATE] && 
    1097                         !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 
    1098                                 sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) 
     1222                    !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 
     1223                                      sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) 
    10991224                { 
    11001225                        if (rinfo[NL80211_RATE_INFO_BITRATE]) 
     
    11131238 
    11141239                if (sinfo[NL80211_STA_INFO_TX_BITRATE] && 
    1115                         !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 
    1116                                 sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) 
     1240                    !nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 
     1241                                      sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) 
    11171242                { 
    11181243                        if (rinfo[NL80211_RATE_INFO_BITRATE]) 
     
    11511276                { 
    11521277                        if (!strncmp(de->d_name, ifname, strlen(ifname)) && 
    1153                                 (!de->d_name[strlen(ifname)] || 
    1154                                 !strncmp(&de->d_name[strlen(ifname)], ".sta", 4))) 
     1278                            (!de->d_name[strlen(ifname)] || 
     1279                            !strncmp(&de->d_name[strlen(ifname)], ".sta", 4))) 
    11551280                        { 
    11561281                                req = nl80211_msg(de->d_name, NL80211_CMD_GET_STATION, 
    1157                                                                   NLM_F_DUMP); 
     1282                                                  NLM_F_DUMP); 
    11581283 
    11591284                                if (req) 
     
    12031328        { 
    12041329                nla_parse(bands, NL80211_BAND_ATTR_MAX, nla_data(band), 
    1205                           nla_len(band), NULL); 
    1206  
    1207                 nla_for_each_nested(freq, 
    1208                         bands[NL80211_BAND_ATTR_FREQS], freqs_remain) 
     1330                          nla_len(band), NULL); 
     1331 
     1332                nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS], freqs_remain) 
    12091333                { 
    12101334                        nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX, 
    1211                                 nla_data(freq), nla_len(freq), freq_policy); 
    1212  
    1213                         ch_cmp = nl80211_freq2channel( 
    1214                                 nla_get_u32(freqs[NL80211_FREQUENCY_ATTR_FREQ])); 
    1215  
    1216                         if( (!ch_cur || (ch_cmp == ch_cur)) && 
    1217                                 freqs[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] ) 
     1335                                  nla_data(freq), nla_len(freq), freq_policy); 
     1336 
     1337                        ch_cmp = nl80211_freq2channel(nla_get_u32( 
     1338                                freqs[NL80211_FREQUENCY_ATTR_FREQ])); 
     1339 
     1340                        if ((!ch_cur || (ch_cmp == ch_cur)) && 
     1341                            freqs[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) 
    12181342                        { 
    12191343                                *dbm_max = (int)(0.01 * nla_get_u32( 
     
    13211445                c->enabled = 0; 
    13221446        } 
     1447} 
     1448 
     1449 
     1450struct nl80211_scanlist { 
     1451        struct iwinfo_scanlist_entry *e; 
     1452        int len; 
     1453}; 
     1454 
     1455 
     1456static void nl80211_get_scanlist_ie(struct nlattr **bss, 
     1457                                    struct iwinfo_scanlist_entry *e) 
     1458{ 
     1459        int ielen = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 
     1460        unsigned char *ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 
     1461        static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 }; 
     1462 
     1463        while (ielen >= 2 && ielen >= ie[1]) 
     1464        { 
     1465                switch (ie[0]) 
     1466                { 
     1467                case 0: /* SSID */ 
     1468                        memcpy(e->ssid, ie + 2, min(ie[1], IWINFO_ESSID_MAX_SIZE)); 
     1469                        break; 
     1470 
     1471                case 48: /* RSN */ 
     1472                        iwinfo_parse_rsn(&e->crypto, ie + 2, ie[1], 
     1473                                         IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x); 
     1474                        break; 
     1475 
     1476                case 221: /* Vendor */ 
     1477                        if (ie[1] >= 4 && !memcmp(ie + 2, ms_oui, 3) && ie[5] == 1) 
     1478                                iwinfo_parse_rsn(&e->crypto, ie + 6, ie[1] - 4, 
     1479                                                 IWINFO_CIPHER_TKIP, IWINFO_KMGMT_PSK); 
     1480                        break; 
     1481                } 
     1482 
     1483                ielen -= ie[1] + 2; 
     1484                ie += ie[1] + 2; 
     1485        } 
     1486} 
     1487 
     1488static int nl80211_get_scanlist_cb(struct nl_msg *msg, void *arg) 
     1489{ 
     1490        int8_t rssi; 
     1491        uint16_t caps; 
     1492 
     1493        struct nl80211_scanlist *sl = arg; 
     1494        struct nlattr **tb = nl80211_parse(msg); 
     1495        struct nlattr *bss[NL80211_BSS_MAX + 1]; 
     1496 
     1497        static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { 
     1498                [NL80211_BSS_TSF]                  = { .type = NLA_U64 }, 
     1499                [NL80211_BSS_FREQUENCY]            = { .type = NLA_U32 }, 
     1500                [NL80211_BSS_BSSID]                = {                 }, 
     1501                [NL80211_BSS_BEACON_INTERVAL]      = { .type = NLA_U16 }, 
     1502                [NL80211_BSS_CAPABILITY]           = { .type = NLA_U16 }, 
     1503                [NL80211_BSS_INFORMATION_ELEMENTS] = {                 }, 
     1504                [NL80211_BSS_SIGNAL_MBM]           = { .type = NLA_U32 }, 
     1505                [NL80211_BSS_SIGNAL_UNSPEC]        = { .type = NLA_U8  }, 
     1506                [NL80211_BSS_STATUS]               = { .type = NLA_U32 }, 
     1507                [NL80211_BSS_SEEN_MS_AGO]          = { .type = NLA_U32 }, 
     1508                [NL80211_BSS_BEACON_IES]           = {                 }, 
     1509        }; 
     1510 
     1511        if (!tb[NL80211_ATTR_BSS] || 
     1512                nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], 
     1513                                 bss_policy) || 
     1514                !bss[NL80211_BSS_BSSID]) 
     1515        { 
     1516                return NL_SKIP; 
     1517        } 
     1518 
     1519        if (bss[NL80211_BSS_CAPABILITY]) 
     1520                caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); 
     1521        else 
     1522                caps = 0; 
     1523 
     1524        memset(sl->e, 0, sizeof(*sl->e)); 
     1525        memcpy(sl->e->mac, nla_data(bss[NL80211_BSS_BSSID]), 6); 
     1526 
     1527        if (caps & (1<<1)) 
     1528                memcpy(sl->e->mode, "Ad-Hoc", 6); 
     1529        else 
     1530                memcpy(sl->e->mode, "Master", 6); 
     1531 
     1532        if (caps & (1<<4)) 
     1533                sl->e->crypto.enabled = 1; 
     1534 
     1535        if (bss[NL80211_BSS_FREQUENCY]) 
     1536                sl->e->channel = nl80211_freq2channel(nla_get_u32( 
     1537                        bss[NL80211_BSS_FREQUENCY])); 
     1538 
     1539        if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) 
     1540                nl80211_get_scanlist_ie(bss, sl->e); 
     1541 
     1542        if (bss[NL80211_BSS_SIGNAL_MBM]) 
     1543        { 
     1544                sl->e->signal = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]) / 100; 
     1545 
     1546                rssi = sl->e->signal - 0x100; 
     1547 
     1548                if (rssi < -110) 
     1549                        rssi = -110; 
     1550                else if (rssi > -40) 
     1551                        rssi = -40; 
     1552 
     1553                sl->e->quality = (rssi + 110); 
     1554                sl->e->quality_max = 70; 
     1555        } 
     1556 
     1557        if (sl->e->crypto.enabled && !sl->e->crypto.wpa_version) 
     1558        { 
     1559                sl->e->crypto.auth_algs    = IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED; 
     1560                sl->e->crypto.pair_ciphers = IWINFO_CIPHER_WEP40 | IWINFO_CIPHER_WEP104; 
     1561        } 
     1562 
     1563        sl->e++; 
     1564        sl->len++; 
     1565 
     1566        return NL_SKIP; 
     1567} 
     1568 
     1569static int nl80211_get_scanlist_nl(const char *ifname, char *buf, int *len) 
     1570{ 
     1571        struct nl_msg *ssids = NULL; 
     1572        struct nl80211_msg_conveyor *req; 
     1573        struct nl80211_scanlist sl = { .e = (struct iwinfo_scanlist_entry *)buf }; 
     1574 
     1575        req = nl80211_msg(ifname, NL80211_CMD_TRIGGER_SCAN, 0); 
     1576        if (req) 
     1577        { 
     1578                nl80211_send(req, NULL, NULL); 
     1579                nl80211_free(req); 
     1580        } 
     1581 
     1582        nl80211_wait("nl80211", "scan", NL80211_CMD_NEW_SCAN_RESULTS); 
     1583 
     1584        req = nl80211_msg(ifname, NL80211_CMD_GET_SCAN, NLM_F_DUMP); 
     1585        if (req) 
     1586        { 
     1587                nl80211_send(req, nl80211_get_scanlist_cb, &sl); 
     1588                nl80211_free(req); 
     1589        } 
     1590 
     1591        *len = sl.len * sizeof(struct iwinfo_scanlist_entry); 
     1592        return *len ? 0 : -1; 
     1593 
     1594nla_put_failure: 
     1595        if (ssids) 
     1596                nlmsg_free(ssids); 
     1597        return -1; 
    13231598} 
    13241599 
     
    13591634 
    13601635                        /* skip header line */ 
    1361                         while( *res++ != '\n' ); 
     1636                        while (*res++ != '\n'); 
    13621637 
    13631638                        count = 0; 
    13641639 
    1365                         while( sscanf(res, "%17s %d %d %255s%*[ \t]%127[^\n]\n", 
    1366                                       bssid, &freq, &rssi, cipher, ssid) > 0 ) 
     1640                        while (sscanf(res, "%17s %d %d %255s%*[ \t]%127[^\n]\n", 
     1641                                      bssid, &freq, &rssi, cipher, ssid) > 0) 
    13671642                        { 
    13681643                                /* BSSID */ 
     
    13751650 
    13761651                                /* SSID */ 
    1377                                 memcpy(e->ssid, ssid, 
    1378                                         min(strlen(ssid), sizeof(e->ssid) - 1)); 
     1652                                memcpy(e->ssid, ssid, min(strlen(ssid), sizeof(e->ssid) - 1)); 
    13791653 
    13801654                                /* Mode (assume master) */ 
     
    14361710                                return -1; 
    14371711 
    1438                         wext_get_scanlist(ifname, buf, len); 
     1712                        nl80211_get_scanlist_nl(ifname, buf, len); 
    14391713                        iwinfo_ifdown(ifname); 
    14401714                        return 0; 
     
    14541728                        if (iwinfo_ifup(res)) 
    14551729                        { 
    1456                                 wext_get_scanlist(res, buf, len); 
     1730                                nl80211_get_scanlist_nl(res, buf, len); 
    14571731                                iwinfo_ifdown(res); 
    14581732                        } 
     
    14621736                        else if (iwinfo_ifdown(ifname) && iwinfo_ifup(res)) 
    14631737                        { 
    1464                                 wext_get_scanlist(res, buf, len); 
     1738                                nl80211_get_scanlist_nl(res, buf, len); 
    14651739                                iwinfo_ifdown(res); 
    14661740                                iwinfo_ifup(ifname); 
     
    15001774        nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain) 
    15011775        { 
    1502                 nla_parse(bands, NL80211_BAND_ATTR_MAX, nla_data(band), 
    1503                         nla_len(band), NULL); 
    1504  
    1505                 nla_for_each_nested(freq, 
    1506                         bands[NL80211_BAND_ATTR_FREQS], freqs_remain) 
     1776                nla_parse(bands, NL80211_BAND_ATTR_MAX, 
     1777                          nla_data(band), nla_len(band), NULL); 
     1778 
     1779                nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS], freqs_remain) 
    15071780                { 
    15081781                        nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX, 
    1509                                 nla_data(freq), nla_len(freq), NULL); 
    1510  
    1511                         if( !freqs[NL80211_FREQUENCY_ATTR_FREQ] || 
    1512                                 freqs[NL80211_FREQUENCY_ATTR_DISABLED] ) 
     1782                                  nla_data(freq), nla_len(freq), NULL); 
     1783 
     1784                        if (!freqs[NL80211_FREQUENCY_ATTR_FREQ] || 
     1785                            freqs[NL80211_FREQUENCY_ATTR_DISABLED]) 
    15131786                                continue; 
    15141787 
     
    15881861        const struct iwinfo_iso3166_label *l; 
    15891862 
    1590         for( l = IWINFO_ISO3166_NAMES, count = 0; l->iso3166; l++, e++, count++ ) 
     1863        for (l = IWINFO_ISO3166_NAMES, count = 0; l->iso3166; l++, e++, count++) 
    15911864        { 
    15921865                e->iso3166 = l->iso3166; 
     
    16151888                nla_for_each_nested(band, attr[NL80211_ATTR_WIPHY_BANDS], bands_remain) 
    16161889                { 
    1617                         nla_parse(bands, NL80211_BAND_ATTR_MAX, nla_data(band), 
    1618                                 nla_len(band), NULL); 
     1890                        nla_parse(bands, NL80211_BAND_ATTR_MAX, 
     1891                                  nla_data(band), nla_len(band), NULL); 
    16191892 
    16201893                        if (bands[NL80211_BAND_ATTR_HT_CAPA]) 
     
    16251898                                *modes |= IWINFO_80211_N; 
    16261899 
    1627                         nla_for_each_nested(freq, 
    1628                                 bands[NL80211_BAND_ATTR_FREQS], freqs_remain) 
     1900                        nla_for_each_nested(freq, bands[NL80211_BAND_ATTR_FREQS], 
     1901                                            freqs_remain) 
    16291902                        { 
    16301903                                nla_parse(freqs, NL80211_FREQUENCY_ATTR_MAX, 
    1631                                         nla_data(freq), nla_len(freq), NULL); 
     1904                                          nla_data(freq), nla_len(freq), NULL); 
    16321905 
    16331906                                if (!freqs[NL80211_FREQUENCY_ATTR_FREQ]) 
     
    17111984        if (rv) 
    17121985        { 
    1713                 rv = iwinfo_hardware_id_from_mtd(buf); 
     1986                rv = iwinfo_hardware_id_from_mtd((struct iwinfo_hardware_id *)buf); 
    17141987        } 
    17151988 
  • trunk/package/iwinfo/src/iwinfo_utils.c

    r30678 r30691  
    146146                        continue; 
    147147 
    148                 return e; 
     148                return (struct iwinfo_hardware_entry *)e; 
    149149        } 
    150150 
     
    222222        return (id->vendor_id && id->device_id) ? 0 : -1; 
    223223} 
     224 
     225void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len, 
     226                                          uint8_t defcipher, uint8_t defauth) 
     227{ 
     228        uint16_t i, count; 
     229 
     230        static unsigned char ms_oui[3]        = { 0x00, 0x50, 0xf2 }; 
     231        static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac }; 
     232 
     233        data += 2; 
     234        len -= 2; 
     235 
     236        if (!memcmp(data, ms_oui, 3)) 
     237                c->wpa_version += 1; 
     238        else if (!memcmp(data, ieee80211_oui, 3)) 
     239                c->wpa_version += 2; 
     240 
     241        if (len < 4) 
     242        { 
     243                c->group_ciphers |= defcipher; 
     244                c->pair_ciphers  |= defcipher; 
     245                c->auth_suites   |= defauth; 
     246                return; 
     247        } 
     248 
     249        if (!memcmp(data, ms_oui, 3) || !memcmp(data, ieee80211_oui, 3)) 
     250        { 
     251                switch (data[3]) 
     252                { 
     253                        case 1: c->group_ciphers |= IWINFO_CIPHER_WEP40;  break; 
     254                        case 2: c->group_ciphers |= IWINFO_CIPHER_TKIP;   break; 
     255                        case 4: c->group_ciphers |= IWINFO_CIPHER_CCMP;   break; 
     256                        case 5: c->group_ciphers |= IWINFO_CIPHER_WEP104; break; 
     257                        case 6:  /* AES-128-CMAC */ break; 
     258                        default: /* proprietary */  break; 
     259                } 
     260        } 
     261 
     262        data += 4; 
     263        len -= 4; 
     264 
     265        if (len < 2) 
     266        { 
     267                c->pair_ciphers |= defcipher; 
     268                c->auth_suites  |= defauth; 
     269                return; 
     270        } 
     271 
     272        count = data[0] | (data[1] << 8); 
     273        if (2 + (count * 4) > len) 
     274                return; 
     275 
     276        for (i = 0; i < count; i++) 
     277        { 
     278                if (!memcmp(data + 2 + (i * 4), ms_oui, 3) || 
     279                        !memcmp(data + 2 + (i * 4), ieee80211_oui, 3)) 
     280                { 
     281                        switch (data[2 + (i * 4) + 3]) 
     282                        { 
     283                                case 1: c->pair_ciphers |= IWINFO_CIPHER_WEP40;  break; 
     284                                case 2: c->pair_ciphers |= IWINFO_CIPHER_TKIP;   break; 
     285                                case 4: c->pair_ciphers |= IWINFO_CIPHER_CCMP;   break; 
     286                                case 5: c->pair_ciphers |= IWINFO_CIPHER_WEP104; break; 
     287                                case 6:  /* AES-128-CMAC */ break; 
     288                                default: /* proprietary */  break; 
     289                        } 
     290                } 
     291        } 
     292 
     293        data += 2 + (count * 4); 
     294        len -= 2 + (count * 4); 
     295 
     296        if (len < 2) 
     297        { 
     298                c->auth_suites |= defauth; 
     299                return; 
     300        } 
     301 
     302        count = data[0] | (data[1] << 8); 
     303        if (2 + (count * 4) > len) 
     304                return; 
     305 
     306        for (i = 0; i < count; i++) 
     307        { 
     308                if (!memcmp(data + 2 + (i * 4), ms_oui, 3) || 
     309                        !memcmp(data + 2 + (i * 4), ieee80211_oui, 3)) 
     310                { 
     311                        switch (data[2 + (i * 4) + 3]) 
     312                        { 
     313                                case 1: c->auth_suites |= IWINFO_KMGMT_8021x; break; 
     314                                case 2: c->auth_suites |= IWINFO_KMGMT_PSK;   break; 
     315                                case 3:  /* FT/IEEE 802.1X */                 break; 
     316                                case 4:  /* FT/PSK */                         break; 
     317                                case 5:  /* IEEE 802.1X/SHA-256 */            break; 
     318                                case 6:  /* PSK/SHA-256 */                    break; 
     319                                default: /* proprietary */                    break; 
     320                        } 
     321                } 
     322        } 
     323 
     324        data += 2 + (count * 4); 
     325        len -= 2 + (count * 4); 
     326} 
  • trunk/package/iwinfo/src/iwinfo_wext_scan.c

    r30672 r30691  
    214214} 
    215215 
    216 static inline void wext_fill_wpa(unsigned char *iebuf, int buflen, struct iwinfo_scanlist_entry *e) 
     216static inline void wext_fill_wpa(unsigned char *iebuf, int ielen, struct iwinfo_scanlist_entry *e) 
    217217{ 
    218         int ielen = iebuf[1] + 2; 
    219         int offset = 2; /* Skip the IE id, and the length. */ 
    220         unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2}; 
    221         unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac}; 
    222         unsigned char *wpa_oui; 
    223         int i; 
    224         uint16_t ver = 0; 
    225         uint16_t cnt = 0; 
    226         int wpa1 = 0, wpa2 = 0; 
    227         char buf[256]; 
    228  
    229         struct iwinfo_crypto_entry *ce = &e->crypto; 
    230  
    231         if(ielen > buflen) 
    232                 ielen = buflen; 
    233  
    234         switch(iebuf[0]) 
    235         { 
    236                 case 0x30:      /* WPA2 */ 
    237                         /* Check if we have enough data */ 
    238                         if(ielen < 4) 
    239                                 return; 
    240  
    241                         wpa_oui = wpa2_oui; 
    242                         break; 
    243  
    244                 case 0xdd:      /* WPA or else */ 
    245                         wpa_oui = wpa1_oui; 
    246                         /* Not all IEs that start with 0xdd are WPA. 
    247                         *        * So check that the OUI is valid. */ 
    248                         if((ielen < 8) || ((memcmp(&iebuf[offset], wpa_oui, 3) != 0) 
    249                                 || (iebuf[offset+3] != 0x01))) 
    250                                         return; 
    251  
    252                         offset += 4; 
    253                         break; 
    254  
    255                 default: 
    256                         return; 
    257         } 
    258  
    259         /* Pick version number (little endian) */ 
    260         ver = iebuf[offset] | (iebuf[offset + 1] << 8); 
    261         offset += 2; 
    262  
    263         if(iebuf[0] == 0xdd) 
    264                 wpa1 = 1; 
    265  
    266         if(iebuf[0] == 0x30) 
    267                 wpa2 = 1; 
    268  
    269         if( wpa1 && (ce->wpa_version == 2) ) 
    270                 ce->wpa_version = 3; 
    271         else if( wpa2 && (ce->wpa_version == 1) ) 
    272                 ce->wpa_version = 3; 
    273         else if( wpa1 && !ce->wpa_version ) 
    274                 ce->wpa_version = 1; 
    275         else if( wpa2 && !ce->wpa_version ) 
    276                 ce->wpa_version = 2; 
    277  
    278         if(ielen < (offset + 4)) 
    279         { 
    280                 ce->group_ciphers |= (1<<2); /* TKIP */ 
    281                 ce->pair_ciphers  |= (1<<2); /* TKIP */ 
    282                 ce->auth_suites   |= (1<<2); /* PSK */ 
    283                 return; 
    284         } 
    285  
    286         if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) 
    287                 ce->group_ciphers |= (1<<7); /* Proprietary */ 
    288         else 
    289                 ce->group_ciphers |= (1<<iebuf[offset+3]); 
    290  
    291         offset += 4; 
    292  
    293         if(ielen < (offset + 2)) 
    294         { 
    295                 ce->pair_ciphers |= (1<<2); /* TKIP */ 
    296                 ce->auth_suites  |= (1<<2); /* PSK */ 
    297                 return; 
    298         } 
    299  
    300         /* Otherwise, we have some number of pairwise ciphers. */ 
    301         cnt = iebuf[offset] | (iebuf[offset + 1] << 8); 
    302         offset += 2; 
    303  
    304         if(ielen < (offset + 4*cnt)) 
    305                 return; 
    306  
    307         *buf = '\0'; 
    308         for(i = 0; i < cnt; i++) 
    309         { 
    310                 if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) 
    311                         ce->pair_ciphers |= (1<<7); /* Proprietary */ 
    312                 else if(iebuf[offset+3] <= IW_IE_CYPHER_NUM) 
    313                         ce->pair_ciphers |= (1<<iebuf[offset+3]); 
    314                 //else 
    315                 //      ce->pair_ciphers[ce->pair_cipher_num++] = 255; /* Unknown */ 
    316  
    317                 offset += 4; 
    318         } 
    319  
    320         /* Check if we are done */ 
    321         if(ielen < (offset + 2)) 
    322                 return; 
    323  
    324         /* Now, we have authentication suites. */ 
    325         cnt = iebuf[offset] | (iebuf[offset + 1] << 8); 
    326         offset += 2; 
    327         *buf = '\0'; 
    328  
    329         if(ielen < (offset + 4*cnt)) 
    330                 return; 
    331  
    332         for(i = 0; i < cnt; i++) 
    333         { 
    334                 if(memcmp(&iebuf[offset], wpa_oui, 3) != 0) 
    335                         ce->auth_suites |= (1<<7); /* Proprietary */ 
    336                 else if(iebuf[offset+3] <= IW_IE_KEY_MGMT_NUM) 
    337                         ce->auth_suites |= (1<<iebuf[offset+3]); 
    338                 //else 
    339                 //      ce->auth_suites[ce->auth_suite_num++] = 255; /* Unknown */ 
    340  
    341                 offset += 4; 
     218        static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 }; 
     219 
     220        while (ielen >= 2 && ielen >= iebuf[1]) 
     221        { 
     222                switch (iebuf[0]) 
     223                { 
     224                case 48: /* RSN */ 
     225                        iwinfo_parse_rsn(&e->crypto, iebuf + 2, iebuf[1], 
     226                                         IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x); 
     227                        break; 
     228 
     229                case 221: /* Vendor */ 
     230                        if (iebuf[1] >= 4 && !memcmp(iebuf + 2, ms_oui, 3) && iebuf[5] == 1) 
     231                                iwinfo_parse_rsn(&e->crypto, iebuf + 6, iebuf[1] - 4, 
     232                                                 IWINFO_CIPHER_TKIP, IWINFO_KMGMT_PSK); 
     233                        break; 
     234                } 
     235 
     236                ielen -= iebuf[1] + 2; 
     237                iebuf += iebuf[1] + 2; 
    342238        } 
    343239} 
     
    434330#endif 
    435331                 case IWEVGENIE: 
    436                         i = 0; 
    437  
    438                         while(i <= (event->u.data.length - 2)) 
    439                         { 
    440                                 switch(((unsigned char *)event->u.data.pointer)[i]) 
    441                                 { 
    442                                         case 0xdd:  /* WPA1 (and other) */ 
    443                                         case 0x30:  /* WPA2 */ 
    444                                                 wext_fill_wpa((unsigned char *)event->u.data.pointer + i, 
    445                                                         event->u.data.length, e); 
    446  
    447                                                 break; 
    448                                 } 
    449  
    450                                 i += ((unsigned char *)event->u.data.pointer)[i+1] + 2; 
    451                         } 
    452  
     332                        wext_fill_wpa(event->u.data.pointer, event->u.data.length, e); 
    453333                        break; 
    454334        } 
Note: See TracChangeset for help on using the changeset viewer.