Browse Source

fix error handling on cache allocation, finish removing all dependency on libnl-cli, add string-based conversion functions for wireless channels

master
Brad Parker 11 years ago
parent
commit
b0f1d1d0eb
  1. 10
      interface.cpp
  2. 7
      iptest/iptest.cpp
  3. 2
      iptest/iptest.pro
  4. 2
      libip.pro
  5. 16
      utils.cpp
  6. 141
      wireless.cpp
  7. 10
      wireless.h

10
interface.cpp

@ -257,13 +257,13 @@ QStringList Interface::addresses() const {
return QStringList(); return QStringList();
} }
if(!(Utils::alloc_addr_cache(sock, &addr_cache))) { if(Utils::alloc_addr_cache(sock, &addr_cache) != 0) {
free(ipInterface); free(ipInterface);
nl_socket_free(sock); nl_socket_free(sock);
return QStringList(); return QStringList();
} }
if(!(Utils::alloc_link_cache(sock, &link_cache))) { if(Utils::alloc_link_cache(sock, &link_cache) != 0) {
free(ipInterface); free(ipInterface);
nl_cache_free(addr_cache); nl_cache_free(addr_cache);
nl_socket_free(sock); nl_socket_free(sock);
@ -338,10 +338,7 @@ QStringList Interface::list() {
return QStringList(); return QStringList();
} }
int ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache); if(Utils::alloc_link_cache(sock, &link_cache) != 0) {
if(ret != 0) {
std::cerr << "could not allocate link cache" << std::endl;
nl_socket_free(sock); nl_socket_free(sock);
return QStringList(); return QStringList();
} }
@ -358,7 +355,6 @@ QStringList Interface::list() {
rtnl_link_put(link); rtnl_link_put(link);
}else{ }else{
rtnl_link_put(link);
break; break;
} }

7
iptest/iptest.cpp

@ -42,14 +42,17 @@ int main(int argc, char *argv[]) {
//interface.deleteAddress("1.1.1.5/29"); //interface.deleteAddress("1.1.1.5/29");
Wireless wi("wlp3s0"); Wireless wi("enp0s3");
QMap<int, int> channels = wi.channels(); QMap<int, int> channels = wi.channelMap();
foreach(int chan, channels.keys()) { foreach(int chan, channels.keys()) {
std::cout << "found channel " << chan << " (" << channels.value(chan) << ")" << std::endl; 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())); QTimer::singleShot(0, qApp, SLOT(quit()));
int ret = app.exec(); int ret = app.exec();

2
iptest/iptest.pro

@ -12,7 +12,7 @@ SOURCES += iptest.cpp
INCLUDEPATH += "../" INCLUDEPATH += "../"
LIBS += -L.. -lip 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_CXXFLAGS += -fsanitize=address -fPIE
QMAKE_CFLAGS += -fsanitize=address -fPIE QMAKE_CFLAGS += -fsanitize=address -fPIE

2
libip.pro

@ -12,7 +12,7 @@ DEFINES += LIBIP_LIBRARY
QMAKE_CXXFLAGS += -Wall -Wextra -Werror -fsanitize=address -fPIE QMAKE_CXXFLAGS += -Wall -Wextra -Werror -fsanitize=address -fPIE
QMAKE_CFLAGS += -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 HEADERS += interface.h neighbor.h wireless.h utils.h
SOURCES += interface.cpp neighbor.cpp wireless.cpp utils.cpp SOURCES += interface.cpp neighbor.cpp wireless.cpp utils.cpp

16
utils.cpp

@ -18,13 +18,13 @@ struct nl_sock* Utils::connect() {
if(sock == NULL) { if(sock == NULL) {
std::cerr << "could not allocate netlink socket" << std::endl; std::cerr << "could not allocate netlink socket" << std::endl;
return 0; return NULL;
} }
if((err = nl_connect(sock, NETLINK_ROUTE)) < 0) { if((err = nl_connect(sock, NETLINK_ROUTE)) < 0) {
std::cerr << "could not connect to netlink socket: " << nl_geterror(err) << std::endl; std::cerr << "could not connect to netlink socket: " << nl_geterror(err) << std::endl;
nl_socket_free(sock); nl_socket_free(sock);
return 0; return NULL;
} }
return sock; 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) { if((err = rtnl_addr_alloc_cache(sock, cache)) < 0) {
std::cerr << "could not allocate address cache: " << nl_geterror(err) << std::endl; std::cerr << "could not allocate address cache: " << nl_geterror(err) << std::endl;
return 0; return 1;
} }
nl_cache_mngt_provide(*cache); 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) { if((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, cache)) < 0) {
std::cerr << "could not allocate link cache: " << nl_geterror(err) << std::endl; std::cerr << "could not allocate link cache: " << nl_geterror(err) << std::endl;
return 0; return 1;
} }
nl_cache_mngt_provide(*cache); 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) { if((err = rtnl_neigh_alloc_cache(sock, cache)) < 0) {
std::cerr << "could not allocate neighbor cache: " << nl_geterror(err) << std::endl; std::cerr << "could not allocate neighbor cache: " << nl_geterror(err) << std::endl;
return 0; return 1;
} }
nl_cache_mngt_provide(*cache); nl_cache_mngt_provide(*cache);
@ -75,15 +75,15 @@ int Utils::interfaceIndex(QString interface) {
if(!sock) { if(!sock) {
std::cerr << "could not allocate socket" << std::endl; std::cerr << "could not allocate socket" << std::endl;
return -1; return 0;
} }
const char *interfaceData = array.constData(); const char *interfaceData = array.constData();
struct nl_cache *link_cache = NULL; 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); nl_socket_free(sock);
return -1; return 0;
} }
int index = rtnl_link_name2i(link_cache, interfaceData); int index = rtnl_link_name2i(link_cache, interfaceData);

141
wireless.cpp

@ -1,8 +1,6 @@
extern "C" { extern "C" {
#include <netlink/cli/utils.h> #include <netlink/genl/ctrl.h>
#include <netlink/cli/neigh.h> #include <netlink/genl/genl.h>
#include <netlink/cli/addr.h>
#include <netlink/cli/link.h>
#include <netlink/genl/family.h> #include <netlink/genl/family.h>
#include <pthread.h> #include <pthread.h>
#include <linux/nl80211.h> #include <linux/nl80211.h>
@ -13,10 +11,7 @@ extern "C" {
#include "utils.h" #include "utils.h"
#include <iostream> #include <iostream>
#include <QStringList> #include <QStringList>
#include <QRegularExpression>
#define BUFLEN 65535
#define MACBUFLEN 18
#define IPBUFLEN 64
struct nl80211_channel_block { struct nl80211_channel_block {
char *phyname; char *phyname;
@ -91,7 +86,9 @@ int IEEE80211Freq[][2] = {
Wireless::Wireless(QString interface) : Wireless::Wireless(QString interface) :
QObject(0), QObject(0),
m_interface(interface), m_interface(interface),
m_channels() m_channels(),
m_isValid(false),
m_isNL80211(false)
{ {
void *handle, *family = NULL; void *handle, *family = NULL;
struct nl_cache *cache = NULL; struct nl_cache *cache = NULL;
@ -104,20 +101,16 @@ m_channels()
cblock.phyname = nl80211_find_parent(interfaceStr); cblock.phyname = nl80211_find_parent(interfaceStr);
if(cblock.phyname != NULL) { if(cblock.phyname == NULL) {
if(strlen(cblock.phyname) == 0) { if(!(Utils::interfaceIndex(interfaceStr))) {
if(Utils::interfaceIndex(interfaceStr) <= 0) { fprintf(stderr, "Interface %s doesn't exist\n", interfaceStr);
fprintf(stderr, "Interface %s doesn't exist\n", interfaceStr); }else{
return; fprintf(stderr, "could not find a parent phy device for interface %s, it isn't nl80211?\n", interfaceStr);
}
fprintf(stderr, "could not find a parent phy device "
"for interface %s, it isn't nl80211?\n", interfaceStr);
return;
} }
}else{
fprintf(stderr, "Interface %s doesn't exist\n", interfaceStr);
return; return;
}else{
m_isNL80211 = true;
} }
if(nl80211_connect(interfaceStr, &handle, &cache, &family) < 0) { if(nl80211_connect(interfaceStr, &handle, &cache, &family) < 0) {
@ -138,7 +131,7 @@ m_channels()
return; return;
} }
while (err) while(err)
nl_recvmsgs((struct nl_sock *)handle, cb); nl_recvmsgs((struct nl_sock *)handle, cb);
nl80211_disconnect(handle, cache); nl80211_disconnect(handle, cache);
@ -149,6 +142,15 @@ m_channels()
free(cblock.channel_list); free(cblock.channel_list);
free(cblock.phyname); free(cblock.phyname);
m_isValid = true;
}
bool Wireless::isValid() {
return m_isValid;
}
bool Wireless::isNL80211() {
return m_isNL80211;
} }
const QString& Wireless::name() const { const QString& Wireless::name() const {
@ -156,31 +158,71 @@ const QString& Wireless::name() const {
} }
int Wireless::ChanToFreq(int in_chan) { int Wireless::ChanToFreq(int in_chan) {
int x = 0; int x = 0;
// 802.11 channels to frequencies
while(IEEE80211Freq[x][0] != 0) {
while (IEEE80211Freq[x][0] != 0) { if(IEEE80211Freq[x][0] == in_chan) {
if (IEEE80211Freq[x][0] == in_chan) { return IEEE80211Freq[x][1];
return IEEE80211Freq[x][1]; }
}
x++; ++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 Wireless::FreqToChan(int in_freq) {
int x = 0; int x = 0;
// 802.11 frequencies to channels
while(IEEE80211Freq[x][1] != 0) {
while (IEEE80211Freq[x][1] != 0) { if(IEEE80211Freq[x][1] == in_freq) {
if (IEEE80211Freq[x][1] == in_freq) { return IEEE80211Freq[x][0];
return IEEE80211Freq[x][0]; }
}
x++; ++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) { 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 (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) { chanb->phyname) != 0) {
return NL_SKIP; return NL_SKIP;
} }
@ -254,7 +296,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) {
// Count the number of channels // Count the number of channels
for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]), for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]),
rem_band = nla_len(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)) { nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) {
nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_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]), for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]),
rem_freq = nla_len(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)) { 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), (struct nlattr *) nla_data(nl_freq),
nla_len(nl_freq), NULL); nla_len(nl_freq), NULL);
@ -286,7 +328,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) {
// Assemble a return // Assemble a return
for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]), for (nl_band = (struct nlattr *) nla_data(tb_msg[NL80211_ATTR_WIPHY_BANDS]),
rem_band = nla_len(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)) { nl_band = (struct nlattr *) nla_next(nl_band, &rem_band)) {
nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_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]), for (nl_freq = (struct nlattr *) nla_data(tb_band[NL80211_BAND_ATTR_FREQS]),
rem_freq = nla_len(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)) { 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), (struct nlattr *) nla_data(nl_freq),
nla_len(nl_freq), NULL); nla_len(nl_freq), NULL);
@ -316,8 +358,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) {
return NL_SKIP; return NL_SKIP;
} }
int Wireless::nl80211_error_cb(struct sockaddr_nl * /*nla*/, struct nlmsgerr *err, int Wireless::nl80211_error_cb(struct sockaddr_nl * /*nla*/, struct nlmsgerr *err, void *arg) {
void *arg) {
int *ret = (int *) arg; int *ret = (int *) arg;
*ret = err->error; *ret = err->error;
return NL_STOP; return NL_STOP;
@ -353,6 +394,6 @@ char* Wireless::nl80211_find_parent(const char *interface) {
return NULL; return NULL;
} }
const QMap<int, int>& Wireless::channels() const { const QMap<int, int>& Wireless::channelMap() const {
return m_channels; return m_channels;
} }

10
wireless.h

@ -11,13 +11,21 @@ Q_OBJECT
public: public:
Wireless(QString interface = QString()); Wireless(QString interface = QString());
const QString& name() const; const QString& name() const;
const QMap<int, int>& channels() const; const QMap<int, int>& channelMap() const;
QVector<int> channels() const;
QVector<int> frequencies() const;
static int ChanToFreq(int in_chan); static int ChanToFreq(int in_chan);
static QString ChanToFreq(QString in_chan, QString outputFormat = QString());
static int FreqToChan(int in_freq); static int FreqToChan(int in_freq);
static QString FreqToChan(QString in_freq, QString outputFormat = QString());
bool isValid();
bool isNL80211();
private: private:
QString m_interface; QString m_interface;
QMap<int, int> m_channels; QMap<int, int> m_channels;
bool m_isValid;
bool m_isNL80211;
static int nl80211_freqlist_cb(struct nl_msg *msg, void *arg); 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_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg);

Loading…
Cancel
Save