Browse Source

add wireless functions to show both all supported frequencies (disabled or not) as well as allowed (RX or both) frequencies, save supported channels as struct with extra info like disabled, radar detection required, max TX power etc.

master
Brad Parker 11 years ago
parent
commit
f8bc2943ed
  1. 50
      iptest/iptest.cpp
  2. 144
      wireless.cpp
  3. 45
      wireless.h

50
iptest/iptest.cpp

@ -44,10 +44,15 @@ int main(int argc, char *argv[]) {
Wireless wi("wlp0s11u1");
QMap<int, int> channels = wi.channelMap();
foreach(int chan, channels.keys()) {
std::cout << "found channel " << chan << " (" << channels.value(chan) << ")" << std::endl;
QList<ChannelInfo> channels = wi.channelMap();
foreach(ChannelInfo info, channels) {
std::cout << "found channel " << info.chan << " (" << info.freq << "): " <<
"Disabled?: " << (info.disabled ? "yes" : "no") << " " <<
"Passive?: " << (info.passive ? "yes" : "no") << " " <<
"Radar?: " << (info.radar ? "yes" : "no") << " " <<
"Max TX Power: " << info.max_txpower <<
std::endl;
}
std::cout << "converting channel 1 to freq: " << qPrintable(Wireless::ChanToFreq("Channel: 1")) << std::endl;
@ -58,6 +63,43 @@ int main(int argc, char *argv[]) {
std::cout << "is frequency 5.825GHz supported? " << (wi.frequencySupported(5825) ? "yes" : "no") << std::endl;
std::cout << "is 802.11a supported? " << (((wi.supportedBands() & Wireless::BAND_80211_A) == Wireless::BAND_80211_A) ? "yes" : "no") << std::endl;
std::cout << "is 802.11b supported? " << (((wi.supportedBands() & Wireless::BAND_80211_B) == Wireless::BAND_80211_B) ? "yes" : "no") << std::endl;
std::cout << "all channels:";
foreach(int chan, wi.allChannels()) {
std::cout << " " << chan;
}
std::cout << std::endl;
////
std::cout << "allowed TX/RX channels:";
foreach(int chan, wi.allowedChannels(Wireless::Direction_Both)) {
std::cout << " " << chan;
}
std::cout << std::endl;
////
std::cout << "allowed RX channels:";
foreach(int chan, wi.allowedChannels(Wireless::Direction_RX)) {
std::cout << " " << chan;
}
std::cout << std::endl;
////
std::cout << "all frequencies:";
foreach(int freq, wi.allFrequencies()) {
std::cout << " " << freq;
}
std::cout << std::endl;
QTimer::singleShot(0, qApp, SLOT(quit()));

144
wireless.cpp

@ -17,13 +17,14 @@ struct nl80211_channel_block {
char *phyname;
int nfreqs;
int *channel_list;
int *disabled_list;
int *passive_list;
int *radar_list;
int *txpower_list;
};
typedef struct nl80211_channel_block nl80211_channel_block_t;
// why is this necessary? I get "SupportedBands does not name a type" if I only declare the typedef in the class definition
typedef QFlags<Wireless::Bands> SupportedBands;
int IEEE80211Freq[][2] = {
{1, 2412},
{2, 2417},
@ -93,7 +94,8 @@ m_channels(),
m_isValid(false),
m_isNL80211(false)
{
void *handle, *family = NULL;
void *handle = NULL;
struct genl_family *family = NULL;
struct nl_cache *cache = NULL;
struct nl_msg *msg = nlmsg_alloc();
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
@ -130,70 +132,137 @@ m_isNL80211(false)
if(nl_send_auto_complete((struct nl_sock *)handle, msg) < 0) {
fprintf(stderr, "%s: Failed to write nl80211 message\n",
__FUNCTION__);
nl80211_disconnect(handle, cache);
nl80211_disconnect(handle, cache, family);
return;
}
while(err)
nl_recvmsgs((struct nl_sock *)handle, cb);
nl80211_disconnect(handle, cache);
nl80211_disconnect(handle, cache, family);
for(int i = 0; i < cblock.nfreqs; ++i) {
m_channels.insert(cblock.channel_list[i], ChanToFreq(cblock.channel_list[i]));
ChannelInfo info;
info.chan = cblock.channel_list[i];
info.freq = ChanToFreq(cblock.channel_list[i]);
info.disabled = cblock.disabled_list[i];
info.passive = cblock.passive_list[i];
info.radar = cblock.radar_list[i];
info.max_txpower = cblock.txpower_list[i];
m_channels.append(info);
// check supported channels to see what bands we support (only makes sense for A and B)
// is there a better way to do this?
if(!((m_supportedBands & BAND_80211_A) == BAND_80211_A)) {
if(cblock.channel_list[i] >= 36) { // first US 5GHz channel
m_supportedBands |= BAND_80211_A;
m_supportedBands = static_cast<Bands>(m_supportedBands | BAND_80211_A);
}
}
if(!((m_supportedBands & BAND_80211_B) == BAND_80211_B)) {
if(cblock.channel_list[i] >= 1) { // first 2.4GHz channel
m_supportedBands |= BAND_80211_B;
m_supportedBands = static_cast<Bands>(m_supportedBands | BAND_80211_B);
}
}
}
free(cblock.channel_list);
free(cblock.disabled_list);
free(cblock.passive_list);
free(cblock.radar_list);
free(cblock.txpower_list);
free(cblock.phyname);
m_isValid = true;
}
const SupportedBands Wireless::supportedBands() const {
Wireless::~Wireless() {
std::cerr << "del wireless" << std::endl;
m_channels.clear();
}
Wireless::Bands Wireless::supportedBands() {
return m_supportedBands;
}
QList<int> Wireless::channels() const {
QList<int> channels = m_channels.keys();
QList<int> Wireless::allChannels() const {
QList<int> channels;
foreach(ChannelInfo info, m_channels) {
channels.append(info.chan);
}
return channels;
}
QList<int> Wireless::frequencies() const {
QList<int> freqs = m_channels.values();
QList<int> Wireless::allowedChannels(Direction dir) const {
QList<int> channels;
foreach(ChannelInfo info, m_channels) {
if(!info.disabled) {
if(((dir & Direction_Both) == Direction_Both) && (!info.passive)) {
channels.append(info.chan);
}else if(((dir & Direction_RX) == Direction_RX)) {
channels.append(info.chan);
}
}
}
return channels;
}
QList<int> Wireless::allFrequencies() const {
QList<int> freqs;
foreach(ChannelInfo info, m_channels) {
freqs.append(info.freq);
}
return freqs;
}
QList<int> Wireless::allowedFrequencies(Direction dir) const {
QList<int> freqs;
foreach(ChannelInfo info, m_channels) {
if(!info.disabled) {
if(((dir & Direction_Both) == Direction_Both) && (!info.passive)) {
freqs.append(info.freq);
}else if(((dir & Direction_RX) == Direction_RX)) {
freqs.append(info.freq);
}
}
}
return freqs;
}
bool Wireless::channelSupported(int chan) const {
if(m_channels.contains(chan)) {
return true;
}else{
return false;
bool found = false;
foreach(ChannelInfo info, m_channels) {
if(info.chan == chan) {
found = true;
break;
}
}
return found;
}
bool Wireless::frequencySupported(int freq) const {
QList<int> channels = m_channels.values();
bool found = false;
if(channels.contains(freq)) {
return true;
}else{
return false;
foreach(ChannelInfo info, m_channels) {
if(info.freq == freq) {
found = true;
break;
}
}
return found;
}
bool Wireless::isValid() const {
@ -276,7 +345,7 @@ QString Wireless::FreqToChan(QString in_freq, QString outputFormat) {
return chan;
}
int Wireless::nl80211_connect(const char * /*interface*/, void **handle, struct nl_cache **cache, void **family) {
int Wireless::nl80211_connect(const char * /*interface*/, void **handle, struct nl_cache **cache, struct genl_family **family) const {
struct nl_sock *nl_handle;
struct nl_cache *nl_cache;
struct genl_family *nl80211;
@ -310,12 +379,13 @@ int Wireless::nl80211_connect(const char * /*interface*/, void **handle, struct
(*handle) = (void *) nl_handle;
(*cache) = nl_cache;
(*family) = (void *) nl80211;
(*family) = nl80211;
return 1;
}
void Wireless::nl80211_disconnect(void *handle, struct nl_cache *cache) {
void Wireless::nl80211_disconnect(void *handle, struct nl_cache *cache, struct genl_family *family) const {
genl_family_put(family);
nl_cache_free(cache);
nl_socket_free((struct nl_sock *)handle);
}
@ -365,15 +435,16 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) {
if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
continue;
if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
continue;
num_freq++;
}
}
chanb->nfreqs = num_freq;
chanb->channel_list = (int*)malloc(sizeof(int) * num_freq);
chanb->disabled_list = (int*)malloc(sizeof(int) * num_freq);
chanb->passive_list = (int*)malloc(sizeof(int) * num_freq);
chanb->radar_list = (int*)malloc(sizeof(int) * num_freq);
chanb->txpower_list = (int*)malloc(sizeof(int) * num_freq);
num_freq = 0;
// Assemble a return
@ -397,12 +468,15 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) {
if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
continue;
if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
continue;
freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
chanb->channel_list[num_freq++] = FreqToChan(freq);
int index = num_freq++;
chanb->channel_list[index] = FreqToChan(freq);
chanb->disabled_list[index] = (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) ? 1 : 0;
chanb->passive_list[index] = (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) ? 1 : 0;
chanb->radar_list[index] = (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) ? 1 : 0;
chanb->txpower_list[index] = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]);
}
}
@ -421,7 +495,7 @@ int Wireless::nl80211_finish_cb(struct nl_msg * /*msg*/, void *arg) {
return NL_SKIP;
}
char* Wireless::nl80211_find_parent(const char *interface) {
char* Wireless::nl80211_find_parent(const char *interface) const {
DIR *devdir;
struct dirent *devfile;
char dirpath[1024];
@ -445,6 +519,6 @@ char* Wireless::nl80211_find_parent(const char *interface) {
return NULL;
}
const QMap<int, int>& Wireless::channelMap() const {
const QList<ChannelInfo>& Wireless::channelMap() const {
return m_channels;
}

45
wireless.h

@ -5,11 +5,31 @@
#include <QMap>
#include "libip_global.h"
struct ChannelInfo {
int chan;
int freq;
bool disabled;
bool passive;
bool radar;
int max_txpower;
ChannelInfo() :
chan(0),
freq(0),
disabled(false),
passive(false),
radar(false),
max_txpower(0)
{
}
};
class LIBIP_EXPORT Wireless : public QObject {
Q_OBJECT
public:
Wireless(QString interface = QString());
~Wireless();
enum Bands {
BAND_80211_A = (1 << 0),
@ -18,12 +38,17 @@ public:
BAND_80211_N = (1 << 3)
};
typedef QFlags<Bands> SupportedBands;
enum Direction {
Direction_RX = (1 << 0),
Direction_Both = (1 << 1)
};
const QString& name() const;
const QMap<int, int>& channelMap() const;
QList<int> channels() const;
QList<int> frequencies() const;
const QList<ChannelInfo>& channelMap() const;
QList<int> allChannels() const;
QList<int> allowedChannels(Direction dir) const;
QList<int> allFrequencies() const;
QList<int> allowedFrequencies(Direction dir) const;
static int ChanToFreq(int in_chan);
static QString ChanToFreq(QString in_chan, QString outputFormat = QString());
static int FreqToChan(int in_freq);
@ -32,21 +57,21 @@ public:
bool isNL80211() const;
bool channelSupported(int chan) const;
bool frequencySupported(int freq) const;
const SupportedBands supportedBands() const;
enum Bands supportedBands();
private:
QString m_interface;
QMap<int, int> m_channels;
QList<ChannelInfo> m_channels;
bool m_isValid;
bool m_isNL80211;
SupportedBands m_supportedBands;
enum Bands m_supportedBands;
static int nl80211_freqlist_cb(struct nl_msg *msg, void *arg);
static int nl80211_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);
static int nl80211_finish_cb(struct nl_msg *msg, void *arg);
static char* nl80211_find_parent(const char *interface);
static void nl80211_disconnect(void *handle, struct nl_cache *cache);
static int nl80211_connect(const char *interface, void **handle, struct nl_cache **cache, void **family);
char* nl80211_find_parent(const char *interface) const;
void nl80211_disconnect(void *handle, struct nl_cache *cache, struct genl_family *family) const;
int nl80211_connect(const char *interface, void **handle, struct nl_cache **cache, struct genl_family **family) const;
};
#endif // LIBIP_WIRELESS_H

Loading…
Cancel
Save