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();
}
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;
}

7
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<int, int> channels = wi.channels();
QMap<int, int> 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();

2
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

2
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

16
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);

141
wireless.cpp

@ -1,8 +1,6 @@
extern "C" {
#include <netlink/cli/utils.h>
#include <netlink/cli/neigh.h>
#include <netlink/cli/addr.h>
#include <netlink/cli/link.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <pthread.h>
#include <linux/nl80211.h>
@ -13,10 +11,7 @@ extern "C" {
#include "utils.h"
#include <iostream>
#include <QStringList>
#define BUFLEN 65535
#define MACBUFLEN 18
#define IPBUFLEN 64
#include <QRegularExpression>
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<int, int>& Wireless::channels() const {
const QMap<int, int>& Wireless::channelMap() const {
return m_channels;
}

10
wireless.h

@ -11,13 +11,21 @@ Q_OBJECT
public:
Wireless(QString interface = QString());
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 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<int, int> 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);

Loading…
Cancel
Save