diff --git a/iptest/iptest.cpp b/iptest/iptest.cpp index 46f2981..5eef904 100644 --- a/iptest/iptest.cpp +++ b/iptest/iptest.cpp @@ -44,10 +44,15 @@ int main(int argc, char *argv[]) { Wireless wi("wlp0s11u1"); - QMap channels = wi.channelMap(); - - foreach(int chan, channels.keys()) { - std::cout << "found channel " << chan << " (" << channels.value(chan) << ")" << std::endl; + QList 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())); diff --git a/wireless.cpp b/wireless.cpp index 886faf8..fe655e2 100644 --- a/wireless.cpp +++ b/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 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(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(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 Wireless::channels() const { - QList channels = m_channels.keys(); +QList Wireless::allChannels() const { + QList channels; + + foreach(ChannelInfo info, m_channels) { + channels.append(info.chan); + } return channels; } -QList Wireless::frequencies() const { - QList freqs = m_channels.values(); +QList Wireless::allowedChannels(Direction dir) const { + QList 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 Wireless::allFrequencies() const { + QList freqs; + + foreach(ChannelInfo info, m_channels) { + freqs.append(info.freq); + } + + return freqs; +} + +QList Wireless::allowedFrequencies(Direction dir) const { + QList 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 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& Wireless::channelMap() const { +const QList& Wireless::channelMap() const { return m_channels; } diff --git a/wireless.h b/wireless.h index 7b8cf30..cec1efa 100644 --- a/wireless.h +++ b/wireless.h @@ -5,11 +5,31 @@ #include #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 SupportedBands; + enum Direction { + Direction_RX = (1 << 0), + Direction_Both = (1 << 1) + }; const QString& name() const; - const QMap& channelMap() const; - QList channels() const; - QList frequencies() const; + const QList& channelMap() const; + QList allChannels() const; + QList allowedChannels(Direction dir) const; + QList allFrequencies() const; + QList 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 m_channels; + QList 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