From b0f1d1d0eb4896795e9e0ee4d7c864434422843b Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 27 Aug 2013 15:30:29 -0400 Subject: [PATCH] fix error handling on cache allocation, finish removing all dependency on libnl-cli, add string-based conversion functions for wireless channels --- interface.cpp | 10 +--- iptest/iptest.cpp | 7 ++- iptest/iptest.pro | 2 +- libip.pro | 2 +- utils.cpp | 16 +++--- wireless.cpp | 141 ++++++++++++++++++++++++++++++---------------- wireless.h | 10 +++- 7 files changed, 118 insertions(+), 70 deletions(-) diff --git a/interface.cpp b/interface.cpp index 9500d1a..71e90d3 100644 --- a/interface.cpp +++ b/interface.cpp @@ -257,13 +257,13 @@ QStringList Interface::addresses() const { return QStringList(); } - if(!(Utils::alloc_addr_cache(sock, &addr_cache))) { + if(Utils::alloc_addr_cache(sock, &addr_cache) != 0) { free(ipInterface); nl_socket_free(sock); return QStringList(); } - if(!(Utils::alloc_link_cache(sock, &link_cache))) { + if(Utils::alloc_link_cache(sock, &link_cache) != 0) { free(ipInterface); nl_cache_free(addr_cache); nl_socket_free(sock); @@ -338,10 +338,7 @@ QStringList Interface::list() { return QStringList(); } - int ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache); - - if(ret != 0) { - std::cerr << "could not allocate link cache" << std::endl; + if(Utils::alloc_link_cache(sock, &link_cache) != 0) { nl_socket_free(sock); return QStringList(); } @@ -358,7 +355,6 @@ QStringList Interface::list() { rtnl_link_put(link); }else{ - rtnl_link_put(link); break; } diff --git a/iptest/iptest.cpp b/iptest/iptest.cpp index 42c5587..4a8c304 100644 --- a/iptest/iptest.cpp +++ b/iptest/iptest.cpp @@ -42,14 +42,17 @@ int main(int argc, char *argv[]) { //interface.deleteAddress("1.1.1.5/29"); - Wireless wi("wlp3s0"); + Wireless wi("enp0s3"); - QMap channels = wi.channels(); + QMap channels = wi.channelMap(); foreach(int chan, channels.keys()) { std::cout << "found channel " << chan << " (" << channels.value(chan) << ")" << std::endl; } + std::cout << "converting channel 1 to freq: " << qPrintable(Wireless::ChanToFreq("Channel: 1")) << std::endl; + std::cout << "converting freq 5200 to channel: " << qPrintable(Wireless::FreqToChan("Frequency: 5.2GHz")) << std::endl; + QTimer::singleShot(0, qApp, SLOT(quit())); int ret = app.exec(); diff --git a/iptest/iptest.pro b/iptest/iptest.pro index 2cbd5f8..5f773d1 100644 --- a/iptest/iptest.pro +++ b/iptest/iptest.pro @@ -12,7 +12,7 @@ SOURCES += iptest.cpp INCLUDEPATH += "../" LIBS += -L.. -lip -LIBS += -lnl-route-3 -lnl-3 -lnl-cli-3 -lasan +LIBS += -lnl-route-3 -lnl-3 -lnl-genl-3 -lasan QMAKE_CXXFLAGS += -fsanitize=address -fPIE QMAKE_CFLAGS += -fsanitize=address -fPIE diff --git a/libip.pro b/libip.pro index 13eaed6..160b916 100644 --- a/libip.pro +++ b/libip.pro @@ -12,7 +12,7 @@ DEFINES += LIBIP_LIBRARY QMAKE_CXXFLAGS += -Wall -Wextra -Werror -fsanitize=address -fPIE QMAKE_CFLAGS += -Wall -Wextra -Werror -fsanitize=address -fPIE -LIBS += -lnl-route-3 -lnl-3 -lnl-cli-3 -lnl-genl-3 -lasan +LIBS += -lnl-route-3 -lnl-3 -lnl-genl-3 -lasan HEADERS += interface.h neighbor.h wireless.h utils.h SOURCES += interface.cpp neighbor.cpp wireless.cpp utils.cpp diff --git a/utils.cpp b/utils.cpp index 698c787..5414b01 100644 --- a/utils.cpp +++ b/utils.cpp @@ -18,13 +18,13 @@ struct nl_sock* Utils::connect() { if(sock == NULL) { std::cerr << "could not allocate netlink socket" << std::endl; - return 0; + return NULL; } if((err = nl_connect(sock, NETLINK_ROUTE)) < 0) { std::cerr << "could not connect to netlink socket: " << nl_geterror(err) << std::endl; nl_socket_free(sock); - return 0; + return NULL; } return sock; @@ -35,7 +35,7 @@ int Utils::alloc_addr_cache(struct nl_sock *sock, struct nl_cache **cache) { if((err = rtnl_addr_alloc_cache(sock, cache)) < 0) { std::cerr << "could not allocate address cache: " << nl_geterror(err) << std::endl; - return 0; + return 1; } nl_cache_mngt_provide(*cache); @@ -48,7 +48,7 @@ int Utils::alloc_link_cache(struct nl_sock *sock, struct nl_cache **cache) { if((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, cache)) < 0) { std::cerr << "could not allocate link cache: " << nl_geterror(err) << std::endl; - return 0; + return 1; } nl_cache_mngt_provide(*cache); @@ -61,7 +61,7 @@ int Utils::alloc_neigh_cache(struct nl_sock *sock, struct nl_cache **cache) { if((err = rtnl_neigh_alloc_cache(sock, cache)) < 0) { std::cerr << "could not allocate neighbor cache: " << nl_geterror(err) << std::endl; - return 0; + return 1; } nl_cache_mngt_provide(*cache); @@ -75,15 +75,15 @@ int Utils::interfaceIndex(QString interface) { if(!sock) { std::cerr << "could not allocate socket" << std::endl; - return -1; + return 0; } const char *interfaceData = array.constData(); struct nl_cache *link_cache = NULL; - if(!(Utils::alloc_link_cache(sock, &link_cache))) { + if(Utils::alloc_link_cache(sock, &link_cache) != 0) { nl_socket_free(sock); - return -1; + return 0; } int index = rtnl_link_name2i(link_cache, interfaceData); diff --git a/wireless.cpp b/wireless.cpp index 12bdeaa..c02e2d9 100644 --- a/wireless.cpp +++ b/wireless.cpp @@ -1,8 +1,6 @@ extern "C" { -#include -#include -#include -#include +#include +#include #include #include #include @@ -13,10 +11,7 @@ extern "C" { #include "utils.h" #include #include - -#define BUFLEN 65535 -#define MACBUFLEN 18 -#define IPBUFLEN 64 +#include struct nl80211_channel_block { char *phyname; @@ -91,7 +86,9 @@ int IEEE80211Freq[][2] = { Wireless::Wireless(QString interface) : QObject(0), m_interface(interface), -m_channels() +m_channels(), +m_isValid(false), +m_isNL80211(false) { void *handle, *family = NULL; struct nl_cache *cache = NULL; @@ -104,20 +101,16 @@ m_channels() cblock.phyname = nl80211_find_parent(interfaceStr); - if(cblock.phyname != NULL) { - if(strlen(cblock.phyname) == 0) { - if(Utils::interfaceIndex(interfaceStr) <= 0) { - fprintf(stderr, "Interface %s doesn't exist\n", interfaceStr); - return; - } - - fprintf(stderr, "could not find a parent phy device " - "for interface %s, it isn't nl80211?\n", interfaceStr); - return; + if(cblock.phyname == NULL) { + if(!(Utils::interfaceIndex(interfaceStr))) { + fprintf(stderr, "Interface %s doesn't exist\n", interfaceStr); + }else{ + fprintf(stderr, "could not find a parent phy device for interface %s, it isn't nl80211?\n", interfaceStr); } - }else{ - fprintf(stderr, "Interface %s doesn't exist\n", interfaceStr); + return; + }else{ + m_isNL80211 = true; } if(nl80211_connect(interfaceStr, &handle, &cache, &family) < 0) { @@ -138,7 +131,7 @@ m_channels() return; } - while (err) + while(err) nl_recvmsgs((struct nl_sock *)handle, cb); nl80211_disconnect(handle, cache); @@ -149,6 +142,15 @@ m_channels() free(cblock.channel_list); free(cblock.phyname); + m_isValid = true; +} + +bool Wireless::isValid() { + return m_isValid; +} + +bool Wireless::isNL80211() { + return m_isNL80211; } const QString& Wireless::name() const { @@ -156,31 +158,71 @@ const QString& Wireless::name() const { } int Wireless::ChanToFreq(int in_chan) { - int x = 0; - // 802.11 channels to frequencies - - while (IEEE80211Freq[x][0] != 0) { - if (IEEE80211Freq[x][0] == in_chan) { - return IEEE80211Freq[x][1]; - } - x++; + int x = 0; + + while(IEEE80211Freq[x][0] != 0) { + if(IEEE80211Freq[x][0] == in_chan) { + return IEEE80211Freq[x][1]; + } + + ++x; + } + + return in_chan; +} + +QString Wireless::ChanToFreq(QString in_chan, QString outputFormat) { + QString freq; + QRegularExpression re("[^\\d]"); + in_chan = in_chan.replace(re, ""); + + if(outputFormat.isEmpty()) { + bool ok = false; + int chanInt = in_chan.toInt(&ok); + + if(ok) { + freq = QString::number(ChanToFreq(chanInt)); } + } - return in_chan; + return freq; } int Wireless::FreqToChan(int in_freq) { - int x = 0; - // 802.11 frequencies to channels - - while (IEEE80211Freq[x][1] != 0) { - if (IEEE80211Freq[x][1] == in_freq) { - return IEEE80211Freq[x][0]; - } - x++; + int x = 0; + + while(IEEE80211Freq[x][1] != 0) { + if(IEEE80211Freq[x][1] == in_freq) { + return IEEE80211Freq[x][0]; + } + + ++x; + } + + return in_freq; +} + +QString Wireless::FreqToChan(QString in_freq, QString outputFormat) { + QString chan; + QRegularExpression re("[^\\d]"); + in_freq = in_freq.replace(re, ""); + + if(in_freq.length() < 4) { + for(int i = in_freq.length() + 1; i <= 4; ++i) { + in_freq.append("0"); + } + } + + if(outputFormat.isEmpty()) { + bool ok = false; + int freqInt = in_freq.toInt(&ok); + + if(ok) { + chan = QString::number(FreqToChan(freqInt)); } + } - return in_freq; + return chan; } int Wireless::nl80211_connect(const char * /*interface*/, void **handle, struct nl_cache **cache, void **family) { @@ -245,7 +287,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { } if (tb_msg[NL80211_ATTR_WIPHY_NAME]) { - if (strcmp(nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]), + if (strcmp(nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]), chanb->phyname) != 0) { return NL_SKIP; } @@ -254,7 +296,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { // Count the number of channels for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]), rem_band = nla_len(tb_msg[NL80211_ATTR_WIPHY_BANDS]); - nla_ok(nl_band, rem_band); + nla_ok(nl_band, rem_band); nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) { nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band), @@ -262,10 +304,10 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]), rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]); - nla_ok(nl_freq, rem_freq); + nla_ok(nl_freq, rem_freq); nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, + nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, (struct nlattr *) nla_data(nl_freq), nla_len(nl_freq), NULL); @@ -286,7 +328,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { // Assemble a return for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]), rem_band = nla_len(tb_msg[NL80211_ATTR_WIPHY_BANDS]); - nla_ok(nl_band, rem_band); + nla_ok(nl_band, rem_band); nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) { nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band), @@ -294,10 +336,10 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]), rem_freq = nla_len(tb_band[NL80211_BAND_ATTR_FREQS]); - nla_ok(nl_freq, rem_freq); + nla_ok(nl_freq, rem_freq); nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) { - nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, + nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, (struct nlattr *) nla_data(nl_freq), nla_len(nl_freq), NULL); @@ -316,8 +358,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { return NL_SKIP; } -int Wireless::nl80211_error_cb(struct sockaddr_nl * /*nla*/, struct nlmsgerr *err, - void *arg) { +int Wireless::nl80211_error_cb(struct sockaddr_nl * /*nla*/, struct nlmsgerr *err, void *arg) { int *ret = (int *) arg; *ret = err->error; return NL_STOP; @@ -353,6 +394,6 @@ char* Wireless::nl80211_find_parent(const char *interface) { return NULL; } -const QMap& Wireless::channels() const { +const QMap& Wireless::channelMap() const { return m_channels; } diff --git a/wireless.h b/wireless.h index 77de780..c3e4d54 100644 --- a/wireless.h +++ b/wireless.h @@ -11,13 +11,21 @@ Q_OBJECT public: Wireless(QString interface = QString()); const QString& name() const; - const QMap& channels() const; + const QMap& channelMap() const; + QVector channels() const; + QVector frequencies() const; static int ChanToFreq(int in_chan); + static QString ChanToFreq(QString in_chan, QString outputFormat = QString()); static int FreqToChan(int in_freq); + static QString FreqToChan(QString in_freq, QString outputFormat = QString()); + bool isValid(); + bool isNL80211(); private: QString m_interface; QMap m_channels; + bool m_isValid; + bool m_isNL80211; 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);