X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=contrib%2Fpackage%2Fiwinfo%2Fsrc%2Fiwinfo_madwifi.c;h=54a77cd4dc5643dac0950bd24decb969aedaab46;hp=9c3bb2688ac213b6eb35c3cfb34a3beff153e1e2;hb=ae33c64a37c8a8d6dc1e38678e967f2e457bc33a;hpb=dabf916db20da0013033efb763b632aecaea20a5 diff --git a/contrib/package/iwinfo/src/iwinfo_madwifi.c b/contrib/package/iwinfo/src/iwinfo_madwifi.c index 9c3bb2688..54a77cd4d 100644 --- a/contrib/package/iwinfo/src/iwinfo_madwifi.c +++ b/contrib/package/iwinfo/src/iwinfo_madwifi.c @@ -1,7 +1,7 @@ /* * iwinfo - Wireless Information Library - Madwifi Backend * - * Copyright (C) 2009 Jo-Philipp Wich + * Copyright (C) 2009-2010 Jo-Philipp Wich * * The iwinfo library is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -196,18 +196,9 @@ static struct ISO3166_to_CCode }; -static int ioctl_socket = -1; - -static int madwifi_ioctl(struct iwreq *wrq, const char *ifname, int cmd, void *data, size_t len) +static int madwifi_wrq(struct iwreq *wrq, const char *ifname, int cmd, void *data, size_t len) { - /* prepare socket */ - if( ioctl_socket == -1 ) - { - ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0); - fcntl(ioctl_socket, F_SETFD, fcntl(ioctl_socket, F_GETFD) | FD_CLOEXEC); - } - - strncpy(wrq->ifr_name, ifname, IFNAMSIZ); + strncpy(wrq->ifr_name, ifname, IFNAMSIZ); if( data != NULL ) { @@ -222,14 +213,14 @@ static int madwifi_ioctl(struct iwreq *wrq, const char *ifname, int cmd, void *d } } - return ioctl(ioctl_socket, cmd, wrq); + return iwinfo_ioctl(cmd, wrq); } static int get80211priv(const char *ifname, int op, void *data, size_t len) { struct iwreq iwr; - if( madwifi_ioctl(&iwr, ifname, op, data, len) < 0 ) + if( madwifi_wrq(&iwr, ifname, op, data, len) < 0 ) return -1; return iwr.u.data.length; @@ -286,6 +277,51 @@ static int madwifi_iswifi(const char *ifname) return ret; } +static char * madwifi_ifadd(const char *ifname) +{ + char *wifidev = NULL; + struct ifreq ifr = { 0 }; + struct ieee80211_clone_params cp = { 0 }; + static char nif[IFNAMSIZ] = { 0 }; + + if( !(wifidev = madwifi_isvap(ifname, NULL)) && madwifi_iswifi(ifname) ) + wifidev = (char *)ifname; + + if( wifidev ) + { + snprintf(nif, sizeof(nif), "tmp.%s", ifname); + + strncpy(cp.icp_name, nif, IFNAMSIZ); + cp.icp_opmode = IEEE80211_M_STA; + cp.icp_flags = IEEE80211_CLONE_BSSID; + + strncpy(ifr.ifr_name, wifidev, IFNAMSIZ); + ifr.ifr_data = (void *)&cp; + + if( !iwinfo_ioctl(SIOC80211IFCREATE, &ifr) ) + { + return nif; + } + else + { + cp.icp_opmode = IEEE80211_M_MONITOR; + + if( !iwinfo_ioctl(SIOC80211IFCREATE, &ifr) ) + return nif; + } + } + + return NULL; +} + +static void madwifi_ifdel(const char *ifname) +{ + struct ifreq ifr = { 0 }; + + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + iwinfo_ioctl(SIOC80211IFDESTROY, &ifr); +} + int madwifi_probe(const char *ifname) { @@ -294,8 +330,7 @@ int madwifi_probe(const char *ifname) void madwifi_close(void) { - if( ioctl_socket > -1 ) - close(ioctl_socket); + /* Nop */ } int madwifi_get_mode(const char *ifname, char *buf) @@ -320,7 +355,7 @@ int madwifi_get_channel(const char *ifname, int *buf) struct iwreq wrq; struct ieee80211req_chaninfo chans; - if( madwifi_ioctl(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 ) + if( madwifi_wrq(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 ) { /* Madwifi returns a Hz frequency, get it's freq list to find channel index */ freq = (uint16_t)(wrq.u.freq.m / 100000); @@ -349,7 +384,7 @@ int madwifi_get_frequency(const char *ifname, int *buf) { struct iwreq wrq; - if( madwifi_ioctl(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 ) + if( madwifi_wrq(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 ) { *buf = (uint16_t)(wrq.u.freq.m / 100000); return 0; @@ -371,7 +406,7 @@ int madwifi_get_bitrate(const char *ifname, int *buf) struct iwreq wrq; struct ieee80211req_sta_info *si; - if( madwifi_ioctl(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 ) + if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 ) { mode = wrq.u.mode; @@ -417,7 +452,7 @@ int madwifi_get_signal(const char *ifname, int *buf) struct iwreq wrq; struct ieee80211req_sta_info *si; - if( madwifi_ioctl(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 ) + if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 ) { mode = wrq.u.mode; @@ -468,7 +503,7 @@ int madwifi_get_quality(const char *ifname, int *buf) struct iwreq wrq; struct ieee80211req_sta_info *si; - if( madwifi_ioctl(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 ) + if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 ) { mode = wrq.u.mode; @@ -513,33 +548,35 @@ int madwifi_get_quality_max(const char *ifname, int *buf) int madwifi_get_encryption(const char *ifname, char *buf) { - int ciphers = 0, key_type = 0, key_len = 0; + 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); - /* Get key information */ - if( get80211priv(ifname, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk)) >= 0 ) - { - key_type = wk.ik_type; + /* Obtain key info */ + if( madwifi_wrq(&wrq, ifname, SIOCGIWENCODE, keybuf, sizeof(keybuf)) < 0 ) + return -1; - /* Type 0 == WEP */ - if( key_type == 0 ) - c->auth_algs = (IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED); - } +#if 0 + /* Have any encryption? */ + if( (wrq.u.data.flags & IW_ENCODE_DISABLED) || (wrq.u.data.length == 0) ) + return 0; +#endif + + /* Save key len */ + key_len = wrq.u.data.length; /* Get wpa protocol version */ wrq.u.mode = IEEE80211_PARAM_WPA; - if( madwifi_ioctl(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) + if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) c->wpa_version = wrq.u.mode; /* Get authentication suites */ wrq.u.mode = IEEE80211_PARAM_AUTHMODE; - if( madwifi_ioctl(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) + if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) { switch(wrq.u.mode) { case IEEE80211_AUTH_8021X: @@ -550,36 +587,50 @@ int madwifi_get_encryption(const char *ifname, char *buf) c->auth_suites |= IWINFO_KMGMT_PSK; break; + case IEEE80211_AUTH_OPEN: + c->auth_algs |= IWINFO_AUTH_OPEN; + break; + + case IEEE80211_AUTH_SHARED: + c->auth_algs |= IWINFO_AUTH_SHARED; + break; + default: c->auth_suites |= IWINFO_KMGMT_NONE; break; } } - /* Get group key length */ - wrq.u.mode = IEEE80211_PARAM_MCASTKEYLEN; - if( madwifi_ioctl(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) - key_len = wrq.u.mode; + 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 ) + { + /* Type 0 == WEP */ + if( (wk.ik_type == 0) && (c->auth_algs == 0) ) + c->auth_algs = (IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED); + } /* Get used pairwise ciphers */ wrq.u.mode = IEEE80211_PARAM_UCASTCIPHERS; - if( madwifi_ioctl(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) + 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) ) + if( !c->pair_ciphers && ciphers & (1 << IEEE80211_CIPHER_WEP) ) { switch(key_len) { case 13: @@ -591,6 +642,8 @@ int madwifi_get_encryption(const char *ifname, char *buf) break; default: + c->pair_ciphers = IWINFO_CIPHER_WEP40 | + IWINFO_CIPHER_WEP104; break; } } @@ -601,11 +654,11 @@ int madwifi_get_encryption(const char *ifname, char *buf) /* Get used group cipher */ wrq.u.mode = IEEE80211_PARAM_MCASTCIPHER; - if( madwifi_ioctl(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 ) + 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; @@ -690,18 +743,15 @@ int madwifi_get_assoclist(const char *ifname, char *buf, int *len) int madwifi_get_txpwrlist(const char *ifname, char *buf, int *len) { int rc = -1; - char cmd[256]; + char *res; /* A wifiX device? */ if( madwifi_iswifi(ifname) ) { - sprintf(cmd, "wlanconfig ath-txpwr create nounit " - "wlandev %s wlanmode ap >/dev/null", ifname); - - if( ! WEXITSTATUS(system(cmd)) ) + if( (res = madwifi_ifadd(ifname)) != NULL ) { - rc = wext_get_txpwrlist("ath-txpwr", buf, len); - (void) WEXITSTATUS(system("wlanconfig ath-txpwr destroy")); + rc = wext_get_txpwrlist(res, buf, len); + madwifi_ifdel(res); } } @@ -717,7 +767,7 @@ int madwifi_get_txpwrlist(const char *ifname, char *buf, int *len) int madwifi_get_scanlist(const char *ifname, char *buf, int *len) { int ret; - char cmd[256]; + char *res; DIR *proc; struct dirent *e; @@ -732,9 +782,7 @@ int madwifi_get_scanlist(const char *ifname, char *buf, int *len) { if( !!madwifi_isvap(e->d_name, ifname) ) { - sprintf(cmd, "ifconfig %s up", e->d_name); - - if( ! WEXITSTATUS(system(cmd)) ) + if( iwinfo_ifup(e->d_name) ) { ret = wext_get_scanlist(e->d_name, buf, len); break; @@ -748,15 +796,21 @@ int madwifi_get_scanlist(const char *ifname, char *buf, int *len) /* Still nothing found, try to create a vap */ if( ret == -1 ) { - sprintf(cmd, "wlanconfig ath-scan create nounit " - "wlandev %s wlanmode sta >/dev/null", ifname); - - if( ! WEXITSTATUS(system(cmd)) && ! WEXITSTATUS(system("ifconfig ath-scan up")) ) + if( (res = madwifi_ifadd(ifname)) != NULL ) { - ret = wext_get_scanlist("ath-scan", buf, len); + if( iwinfo_ifup(res) ) + { + wext_get_scanlist(res, buf, len); + sleep(1); + + wext_get_scanlist(res, buf, len); + sleep(1); - (void) WEXITSTATUS(system("ifconfig ath-scan down")); - (void) WEXITSTATUS(system("wlanconfig ath-scan destroy")); + ret = wext_get_scanlist(res, buf, len); + } + + iwinfo_ifdown(res); + madwifi_ifdel(res); } } } @@ -774,27 +828,27 @@ int madwifi_get_freqlist(const char *ifname, char *buf, int *len) { int i, bl; int rc = -1; - char cmd[256]; + char *res; struct ieee80211req_chaninfo chans; struct iwinfo_freqlist_entry entry; /* A wifiX device? */ if( madwifi_iswifi(ifname) ) { - sprintf(cmd, "wlanconfig ath-channels create nounit " - "wlandev %s wlanmode ap >/dev/null", ifname); - - if( ! WEXITSTATUS(system(cmd)) ) + if( (res = madwifi_ifadd(ifname)) != NULL ) { - rc = get80211priv("ath-channels", IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)); - (void) WEXITSTATUS(system("wlanconfig ath-channels destroy")); + rc = get80211priv(res, IEEE80211_IOCTL_GETCHANINFO, + &chans, sizeof(chans)); + + madwifi_ifdel(res); } } /* Its an athX ... */ else if( !!madwifi_isvap(ifname, NULL) ) { - rc = get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)); + rc = get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, + &chans, sizeof(chans)); } @@ -805,8 +859,9 @@ int madwifi_get_freqlist(const char *ifname, char *buf, int *len) for( i = 0; i < chans.ic_nchans; i++ ) { - entry.mhz = chans.ic_chans[i].ic_freq; - entry.channel = chans.ic_chans[i].ic_ieee; + entry.mhz = chans.ic_chans[i].ic_freq; + entry.channel = chans.ic_chans[i].ic_ieee; + entry.restricted = 0; memcpy(&buf[bl], &entry, sizeof(struct iwinfo_freqlist_entry)); bl += sizeof(struct iwinfo_freqlist_entry); @@ -885,9 +940,47 @@ int madwifi_get_countrylist(const char *ifname, char *buf, int *len) return 0; } +int madwifi_get_hwmodelist(const char *ifname, int *buf) +{ + char chans[IWINFO_BUFSIZE] = { 0 }; + struct iwinfo_freqlist_entry *e = NULL; + int len = 0; + + if( !madwifi_get_freqlist(ifname, chans, &len) ) + { + for( e = (struct iwinfo_freqlist_entry *)chans; e->channel; e++ ) + { + if( e->channel <= 14 ) + { + *buf |= IWINFO_80211_B; + *buf |= IWINFO_80211_G; + } + else + { + *buf |= IWINFO_80211_A; + } + } + + return 0; + } + + return -1; +} + int madwifi_get_mbssid_support(const char *ifname, int *buf) { - /* We assume that multi bssid is always possible */ - *buf = 1; - return 0; + /* Test whether we can create another interface */ + char *nif = madwifi_ifadd(ifname); + + if( nif ) + { + *buf = iwinfo_ifup(nif); + + iwinfo_ifdown(nif); + madwifi_ifdel(nif); + + return 0; + } + + return -1; }