Browse Source

move interface->index mapping to separate Utils class, initial work on Wireless class, currently gets list of supported frequencies but they aren't returned yet

master
Brad Parker 11 years ago
parent
commit
c1303d8c1d
  1. 27
      interface.cpp
  2. 6
      interface.h
  3. 5
      iptest/iptest.cpp
  4. 6
      libip.pro
  5. 2
      neighbor.cpp
  6. 8
      neighbor.h
  7. 38
      utils.cpp
  8. 13
      utils.h
  9. 342
      wireless.cpp
  10. 18
      wireless.h

27
interface.cpp

@ -15,10 +15,11 @@ extern "C" {
}
#include "interface.h"
#include "utils.h"
#include <iostream>
#include <QStringList>
#include <QTimer>
#include <QtGui/QGuiApplication>
#include <QtCore/QCoreApplication>
#define BUFLEN 65535
#define ADDRBUFLEN BUFLEN
@ -28,29 +29,7 @@ QObject(0),
m_interface(interface),
m_index(-1)
{
QByteArray array = interface.toLatin1();
struct nl_sock *sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
const char *interfaceData = array.constData();
struct nl_cache *link_cache;
int ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache);
if(ret != 0) {
std::cerr << "could not allocate link cache" << std::endl;
QTimer::singleShot(0, qApp, SLOT(quit()));
return;
}
int index = rtnl_link_name2i(link_cache, interfaceData);
m_index = index;
nl_cache_free(link_cache);
nl_socket_free(sock);
m_index = Utils::interfaceIndex(interface);
}
void Interface::addAddress(QString addressStr) const {

6
interface.h

@ -1,5 +1,5 @@
#ifndef INTERFACE_H
#define INTERFACE_H
#ifndef LIBIP_INTERFACE_H
#define LIBIP_INTERFACE_H
#include <QObject>
@ -20,4 +20,4 @@ private:
int m_index;
};
#endif // INTERFACE_H
#endif // LIBIP_INTERFACE_H

5
iptest/iptest.cpp

@ -4,6 +4,7 @@
#include <QStringList>
#include "interface.h"
#include "neighbor.h"
#include "wireless.h"
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
@ -41,6 +42,10 @@ int main(int argc, char *argv[]) {
//interface.deleteAddress("1.1.1.5/29");
Wireless wi("wlp3s0");
wi.info();
QTimer::singleShot(0, qApp, SLOT(quit()));
int ret = app.exec();

6
libip.pro

@ -10,7 +10,7 @@ INCLUDEPATH += /usr/include/libnl3
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 -lasan
LIBS += -lnl-route-3 -lnl-3 -lnl-cli-3 -lnl-genl-3 -lasan
HEADERS += interface.h neighbor.h
SOURCES += interface.cpp neighbor.cpp
HEADERS += interface.h neighbor.h wireless.h utils.h
SOURCES += interface.cpp neighbor.cpp wireless.cpp utils.cpp

2
neighbor.cpp

@ -145,6 +145,6 @@ QStringList Neighbor::list(QString interfaceString) {
return neighborList;
}
const QString Neighbor::name() const {
const QString& Neighbor::name() const {
return m_interface;
}

8
neighbor.h

@ -1,5 +1,5 @@
#ifndef NEIGHBOR_H
#define NEIGHBOR_H
#ifndef LIBIP_NEIGHBOR_H
#define LIBIP_NEIGHBOR_H
#include <QObject>
@ -10,10 +10,10 @@ public:
Neighbor(QString interface = QString());
QString macOfIP(QString ip) const;
static QStringList list(QString interface = QString());
const QString name() const;
const QString& name() const;
private:
QString m_interface;
};
#endif // NEIGHBOR_H
#endif // LIBIP_NEIGHBOR_H

38
utils.cpp

@ -0,0 +1,38 @@
extern "C" {
#include <netlink/cli/utils.h>
#include <netlink/cli/neigh.h>
#include <netlink/cli/addr.h>
#include <netlink/cli/link.h>
#include <pthread.h>
}
#include "utils.h"
#include <iostream>
#include <QTimer>
#include <QtCore/QCoreApplication>
int Utils::interfaceIndex(QString interface) {
QByteArray array = interface.toLatin1();
struct nl_sock *sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
const char *interfaceData = array.constData();
struct nl_cache *link_cache;
int ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache);
if(ret != 0) {
std::cerr << "could not allocate link cache" << std::endl;
QTimer::singleShot(0, qApp, SLOT(quit()));
return -1;
}
int index = rtnl_link_name2i(link_cache, interfaceData);
nl_cache_free(link_cache);
nl_socket_free(sock);
return index;
}

13
utils.h

@ -0,0 +1,13 @@
#ifndef LIBIP_UTILS_H
#define LIBIP_UTILS_H
#include <QObject>
class Q_DECL_EXPORT Utils : public QObject {
Q_OBJECT
public:
static int interfaceIndex(QString interface);
};
#endif // LIBIP_UTILS_H

342
wireless.cpp

@ -0,0 +1,342 @@
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/family.h>
#include <pthread.h>
#include <linux/nl80211.h>
#include <dirent.h>
}
#include "wireless.h"
#include "utils.h"
#include <iostream>
#include <QStringList>
#define BUFLEN 65535
#define MACBUFLEN 18
#define IPBUFLEN 64
struct nl80211_channel_block {
char *phyname;
int nfreqs;
int *channel_list;
};
typedef struct nl80211_channel_block nl80211_channel_block_t;
int IEEE80211Freq[][2] = {
{1, 2412},
{2, 2417},
{3, 2422},
{4, 2427},
{5, 2432},
{6, 2437},
{7, 2442},
{8, 2447},
{9, 2452},
{10, 2457},
{11, 2462},
{12, 2467},
{13, 2472},
{14, 2484},
// We could do the math here, but what about 4ghz nonsense?
// We'll do table lookups for now.
{36, 5180},
{37, 5185},
{38, 5190},
{39, 5195},
{40, 5200},
{41, 5205},
{42, 5210},
{43, 5215},
{44, 5220},
{45, 5225},
{46, 5230},
{47, 5235},
{48, 5240},
{52, 5260},
{53, 5265},
{54, 5270},
{55, 5275},
{56, 5280},
{57, 5285},
{58, 5290},
{59, 5295},
{60, 5300},
{64, 5320},
{149, 5745},
{150, 5750},
{152, 5760},
{153, 5765},
{157, 5785},
{160, 5800},
{161, 5805},
{165, 5825},
{0, 0}
};
Wireless::Wireless(QString interface) :
QObject(0),
m_interface(interface)
{
}
const QString& Wireless::name() const {
return m_interface;
}
int ChanToFreq(int in_chan) {
int x = 0;
// 80211b frequencies to channels
while (IEEE80211Freq[x][0] != 0) {
if (IEEE80211Freq[x][0] == in_chan) {
return IEEE80211Freq[x][1];
}
x++;
}
return in_chan;
}
int FreqToChan(int in_freq) {
int x = 0;
// 80211b frequencies to channels
while (IEEE80211Freq[x][1] != 0) {
if (IEEE80211Freq[x][1] == in_freq) {
return IEEE80211Freq[x][0];
}
x++;
}
return in_freq;
}
int nl80211_connect(const char * /*interface*/, void **handle, void **cache, void **family) {
struct nl_sock *nl_handle;
struct nl_cache *nl_cache;
struct genl_family *nl80211;
if((nl_handle = nl_socket_alloc()) == NULL) {
fprintf(stderr, "%s failed to allocate nlhandle",
__FUNCTION__);
return -1;
}
if(genl_connect(nl_handle)) {
fprintf(stderr, "%s failed to connect to generic netlink",
__FUNCTION__);
nl_socket_free(nl_handle);
return -1;
}
if(genl_ctrl_alloc_cache(nl_handle, &nl_cache) != 0) {
fprintf(stderr, "%s failed to allocate "
"generic netlink cache", __FUNCTION__);
nl_socket_free(nl_handle);
return -1;
}
if ((nl80211 = genl_ctrl_search_by_name(nl_cache, "nl80211")) == NULL) {
fprintf(stderr, "%s failed to find "
"nl80211 controls, kernel may be too old", __FUNCTION__);
nl_socket_free(nl_handle);
return -1;
}
(*handle) = (void *) nl_handle;
(*cache) = (void *) nl_cache;
(*family) = (void *) nl80211;
return 1;
}
void nl80211_disconnect(void *handle) {
nl_socket_free((struct nl_sock *)handle);
}
static int nl80211_freqlist_cb(struct nl_msg *msg, void *arg) {
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = (struct genlmsghdr *) nlmsg_data(nlmsg_hdr(msg));
struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
struct nlattr *nl_band, *nl_freq;
int rem_band, rem_freq, num_freq = 0;
uint32_t freq;
struct nl80211_channel_block *chanb = (struct nl80211_channel_block *) arg;
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) {
return NL_SKIP;
}
if (tb_msg[NL80211_ATTR_WIPHY_NAME]) {
if (strcmp(nla_get_string(tb_msg[NL80211_ATTR_WIPHY_NAME]),
chanb->phyname) != 0) {
return NL_SKIP;
}
}
// 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);
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_len(nl_band), NULL);
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);
nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) {
nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
(struct nlattr *) nla_data(nl_freq),
nla_len(nl_freq), NULL);
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);
num_freq = 0;
// 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);
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_len(nl_band), NULL);
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);
nl_freq = (struct nlattr *) nla_next(nl_freq, &rem_freq)) {
nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
(struct nlattr *) nla_data(nl_freq),
nla_len(nl_freq), NULL);
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);
}
}
return NL_SKIP;
}
static int nl80211_error_cb(struct sockaddr_nl * /*nla*/, struct nlmsgerr *err,
void *arg) {
int *ret = (int *) arg;
*ret = err->error;
return NL_STOP;
}
static int nl80211_finish_cb(struct nl_msg * /*msg*/, void *arg) {
int *ret = (int *) arg;
*ret = 0;
return NL_SKIP;
}
char* nl80211_find_parent(const char *interface) {
DIR *devdir;
struct dirent *devfile;
char dirpath[1024];
char *ret;
snprintf(dirpath, 1024, "/sys/class/net/%s/phy80211/device/ieee80211", interface);
if ((devdir = opendir(dirpath)) == NULL)
return NULL;
while ((devfile = readdir(devdir)) != NULL) {
std::cerr << "reading dir " << devfile->d_name << std::endl;
if(strncmp("phy", devfile->d_name, 3) == 0) {
std::cerr << "found phy " << devfile->d_name << std::endl;
ret = strdup(devfile->d_name);
closedir(devdir);
return ret;
}
}
closedir(devdir);
return NULL;
}
void Wireless::info() {
void *handle, *cache, *family = NULL;
struct nl_msg *msg = nlmsg_alloc();
struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
nl80211_channel_block_t cblock;
QByteArray interfaceArray = m_interface.toLatin1();
const char *interface = interfaceArray.constData();
int err = 1;
cblock.phyname = nl80211_find_parent(interface);
if(strlen(cblock.phyname) == 0) {
if(Utils::interfaceIndex(interface) <= 0) {
fprintf(stderr, "Interface %s doesn't exist", interface);
return;
}
fprintf(stderr, "could not find a parent phy device "
"for interface %s, it isn't nl80211?", interface);
return;
}
if(nl80211_connect(interface, &handle, &cache, &family) < 0) {
std::cerr << "could not connect to nl80211" << std::endl;
return;
}
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_freqlist_cb, &cblock);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_finish_cb, &err);
nl_cb_err(cb, NL_CB_CUSTOM, nl80211_error_cb, &err);
genlmsg_put(msg, 0, 0, genl_family_get_id((struct genl_family *)family), 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
if(nl_send_auto_complete((struct nl_sock *)handle, msg) < 0) {
fprintf(stderr, "%s: Failed to write nl80211 message",
__FUNCTION__);
nl80211_disconnect(handle);
}
while (err)
nl_recvmsgs((struct nl_sock *)handle, cb);
nl80211_disconnect(handle);
std::cout << "num freqs: " << cblock.nfreqs << std::endl;
std::cout << "size of freqs: " << (sizeof(int) * cblock.nfreqs) << std::endl;
//memcpy(*ret_chan_list, cblock.channel_list, sizeof(int) * cblock.nfreqs);
free(cblock.channel_list);
free(cblock.phyname);
}

18
wireless.h

@ -0,0 +1,18 @@
#ifndef LIBIP_WIRELESS_H
#define LIBIP_WIRELESS_H
#include <QObject>
class Q_DECL_EXPORT Wireless : public QObject {
Q_OBJECT
public:
Wireless(QString interface = QString());
const QString& name() const;
void info();
private:
QString m_interface;
};
#endif // LIBIP_WIRELESS_H
Loading…
Cancel
Save