|
|
@ -81,7 +81,13 @@ int IEEE80211Freq[][2] = { |
|
|
|
|
|
|
|
struct nl_callback { |
|
|
|
char *phyname; |
|
|
|
void *bands; |
|
|
|
void *extra; |
|
|
|
}; |
|
|
|
|
|
|
|
struct nl_interfaceCallback { |
|
|
|
char *ifname; |
|
|
|
nl80211_iftype *iftype; |
|
|
|
QString *iftypeString; |
|
|
|
}; |
|
|
|
|
|
|
|
/*!
|
|
|
@ -95,10 +101,38 @@ struct nl_callback { |
|
|
|
Wireless::Wireless(QString interface) : |
|
|
|
QObject(0), |
|
|
|
m_interface(interface), |
|
|
|
m_interfaceType(), |
|
|
|
m_bands(), |
|
|
|
m_isValid(false), |
|
|
|
m_isNL80211(false) |
|
|
|
m_isNL80211(false), |
|
|
|
m_iftype(NL80211_IFTYPE_UNSPECIFIED) |
|
|
|
{ |
|
|
|
if(parseBands() && parseInterface()) { |
|
|
|
m_isValid = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Wireless::~Wireless() { |
|
|
|
std::cerr << "del wireless" << std::endl; |
|
|
|
|
|
|
|
m_bands.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
QStringList Wireless::interfaceList() { |
|
|
|
QStringList interfaces = Interface::list(); |
|
|
|
|
|
|
|
foreach(QString interface, interfaces) { |
|
|
|
Wireless wir(interface); |
|
|
|
|
|
|
|
if(!wir.isValid()) { |
|
|
|
interfaces.removeAll(interface); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return interfaces; |
|
|
|
} |
|
|
|
|
|
|
|
bool Wireless::parseBands() { |
|
|
|
void *handle = NULL; |
|
|
|
struct genl_family *family = NULL; |
|
|
|
struct nl_cache *cache = NULL; |
|
|
@ -117,18 +151,23 @@ m_isNL80211(false) |
|
|
|
fprintf(stderr, "could not find a parent phy device for interface %s, it isn't nl80211?\n", interfaceStr); |
|
|
|
} |
|
|
|
|
|
|
|
return; |
|
|
|
nlmsg_free(msg); |
|
|
|
nl_cb_put(cb); |
|
|
|
return false; |
|
|
|
}else{ |
|
|
|
m_isNL80211 = true; |
|
|
|
} |
|
|
|
|
|
|
|
if(nl80211_connect(interfaceStr, &handle, &cache, &family) < 0) { |
|
|
|
std::cerr << "could not connect to nl80211" << std::endl; |
|
|
|
return; |
|
|
|
nlmsg_free(msg); |
|
|
|
nl_cb_put(cb); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
struct nl_callback callback = { .phyname = phyname, .bands = &m_bands }; |
|
|
|
struct nl_callback callback = { .phyname = phyname, .extra = &m_bands }; |
|
|
|
|
|
|
|
// freqlist
|
|
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, nl80211_freqlist_cb, &callback); |
|
|
|
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); |
|
|
@ -139,35 +178,80 @@ m_isNL80211(false) |
|
|
|
fprintf(stderr, "%s: Failed to write nl80211 message\n", |
|
|
|
__FUNCTION__); |
|
|
|
nl80211_disconnect(handle, cache, family); |
|
|
|
return; |
|
|
|
nlmsg_free(msg); |
|
|
|
nl_cb_put(cb); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
while(err) |
|
|
|
nl_recvmsgs((struct nl_sock *)handle, cb); |
|
|
|
|
|
|
|
nl80211_disconnect(handle, cache, family); |
|
|
|
nlmsg_free(msg); |
|
|
|
nl_cb_put(cb); |
|
|
|
|
|
|
|
m_isValid = true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
Wireless::~Wireless() { |
|
|
|
std::cerr << "del wireless" << std::endl; |
|
|
|
bool Wireless::parseInterface() { |
|
|
|
void *handle = NULL; |
|
|
|
struct genl_family *family = NULL; |
|
|
|
struct nl_cache *cache = NULL; |
|
|
|
struct nl_msg *msgInterface = nlmsg_alloc(); |
|
|
|
struct nl_cb *cbInterface = nl_cb_alloc(NL_CB_DEFAULT); |
|
|
|
QByteArray interfaceArray = m_interface.toLatin1(); |
|
|
|
const char *interfaceStr = interfaceArray.constData(); |
|
|
|
char *interfaceData = interfaceArray.data(); |
|
|
|
int err = 1; |
|
|
|
|
|
|
|
m_bands.clear(); |
|
|
|
} |
|
|
|
char *phyname = nl80211_find_parent(interfaceStr); |
|
|
|
|
|
|
|
QStringList Wireless::interfaceList() { |
|
|
|
QStringList interfaces = Interface::list(); |
|
|
|
if(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); |
|
|
|
} |
|
|
|
|
|
|
|
foreach(QString interface, interfaces) { |
|
|
|
Wireless wir(interface); |
|
|
|
nlmsg_free(msgInterface); |
|
|
|
nl_cb_put(cbInterface); |
|
|
|
return false; |
|
|
|
}else{ |
|
|
|
m_isNL80211 = true; |
|
|
|
} |
|
|
|
|
|
|
|
if(!wir.isValid()) { |
|
|
|
interfaces.removeAll(interface); |
|
|
|
} |
|
|
|
if(nl80211_connect(interfaceStr, &handle, &cache, &family) < 0) { |
|
|
|
std::cerr << "could not connect to nl80211" << std::endl; |
|
|
|
nlmsg_free(msgInterface); |
|
|
|
nl_cb_put(cbInterface); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
return interfaces; |
|
|
|
struct nl_interfaceCallback callback = { .ifname = interfaceData, .iftype = &m_iftype, .iftypeString = &m_interfaceType}; |
|
|
|
|
|
|
|
nl_cb_set(cbInterface, NL_CB_VALID, NL_CB_CUSTOM, nl80211_interface_cb, &callback); |
|
|
|
nl_cb_set(cbInterface, NL_CB_FINISH, NL_CB_CUSTOM, nl80211_finish_cb, &err); |
|
|
|
nl_cb_err(cbInterface, NL_CB_CUSTOM, nl80211_error_cb, &err); |
|
|
|
|
|
|
|
genlmsg_put(msgInterface, 0, 0, genl_family_get_id((struct genl_family *)family), 0, NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0); |
|
|
|
|
|
|
|
if(nl_send_auto_complete((struct nl_sock *)handle, msgInterface) < 0) { |
|
|
|
fprintf(stderr, "%s: Failed to write nl80211 message\n", |
|
|
|
__FUNCTION__); |
|
|
|
nl80211_disconnect(handle, cache, family); |
|
|
|
nlmsg_free(msgInterface); |
|
|
|
nl_cb_put(cbInterface); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
while(err) |
|
|
|
nl_recvmsgs((struct nl_sock *)handle, cbInterface); |
|
|
|
|
|
|
|
nl80211_disconnect(handle, cache, family); |
|
|
|
nlmsg_free(msgInterface); |
|
|
|
nl_cb_put(cbInterface); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
/*!
|
|
|
@ -424,12 +508,62 @@ void Wireless::nl80211_disconnect(void *handle, struct nl_cache *cache, struct g |
|
|
|
nl_socket_free((struct nl_sock *)handle); |
|
|
|
} |
|
|
|
|
|
|
|
nl80211_iftype Wireless::getInterfaceTypeRaw() { |
|
|
|
return m_iftype; |
|
|
|
} |
|
|
|
|
|
|
|
const QString& Wireless::getInterfaceType() const { |
|
|
|
return m_interfaceType; |
|
|
|
} |
|
|
|
|
|
|
|
int Wireless::nl80211_interface_cb(struct nl_msg *msg, void *arg) { |
|
|
|
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1] = {NULL}; |
|
|
|
struct genlmsghdr *gnlh = (struct genlmsghdr *) nlmsg_data(nlmsg_hdr(msg)); |
|
|
|
//struct nlattr *tb_interface[NL80211_IFTYPE_MAX + 1];
|
|
|
|
//struct nlattr *nl_interface = NULL;
|
|
|
|
//int rem_interface = 0;
|
|
|
|
struct nl_interfaceCallback *callback = (struct nl_interfaceCallback*)arg; |
|
|
|
|
|
|
|
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), |
|
|
|
genlmsg_attrlen(gnlh, 0), NULL); |
|
|
|
|
|
|
|
if (!tb_msg[NL80211_ATTR_IFTYPE]) { |
|
|
|
return NL_SKIP; |
|
|
|
} |
|
|
|
|
|
|
|
if (tb_msg[NL80211_ATTR_IFNAME]) { |
|
|
|
if (strcmp(nla_get_string(tb_msg[NL80211_ATTR_IFNAME]), |
|
|
|
callback->ifname) != 0) { |
|
|
|
return NL_SKIP; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
*(callback->iftype) = static_cast<nl80211_iftype>(nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE])); |
|
|
|
|
|
|
|
switch(*(callback->iftype)) { |
|
|
|
case NL80211_IFTYPE_UNSPECIFIED: { *(callback->iftypeString) = "Unspecified"; break; } |
|
|
|
case NL80211_IFTYPE_ADHOC: { *(callback->iftypeString) = "Ad-hoc"; break; } |
|
|
|
case NL80211_IFTYPE_STATION: { *(callback->iftypeString) = "Client"; break; } |
|
|
|
case NL80211_IFTYPE_AP: { *(callback->iftypeString) = "AP"; break; } |
|
|
|
case NL80211_IFTYPE_AP_VLAN: { *(callback->iftypeString) = "AP-VLAN"; break; } |
|
|
|
case NL80211_IFTYPE_WDS: { *(callback->iftypeString) = "WDS"; break; } |
|
|
|
case NL80211_IFTYPE_MONITOR: { *(callback->iftypeString) = "Monitor"; break; } |
|
|
|
case NL80211_IFTYPE_MESH_POINT: { *(callback->iftypeString) = "Mesh Point"; break; } |
|
|
|
case NL80211_IFTYPE_P2P_CLIENT: { *(callback->iftypeString) = "P2P Client"; break; } |
|
|
|
case NL80211_IFTYPE_P2P_GO: { *(callback->iftypeString) = "P2P Go"; break; } |
|
|
|
case NL80211_IFTYPE_P2P_DEVICE: { *(callback->iftypeString) = "P2P Device"; break; } |
|
|
|
default: { *(callback->iftypeString) = "Unspecified"; break; } |
|
|
|
} |
|
|
|
|
|
|
|
return NL_SKIP; |
|
|
|
} |
|
|
|
|
|
|
|
int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { |
|
|
|
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; |
|
|
|
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1] = {NULL}; |
|
|
|
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; |
|
|
|
struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1] = {NULL}; |
|
|
|
struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1] = {NULL}; |
|
|
|
struct nlattr *nl_band, *nl_freq = NULL; |
|
|
|
int rem_band, rem_freq = 0; |
|
|
|
struct nl_callback *callback = (struct nl_callback*)arg; |
|
|
|
|
|
|
@ -456,7 +590,7 @@ int Wireless::nl80211_freqlist_cb(struct nl_msg *msg, void *arg) { |
|
|
|
nla_parse(tb_band, NL80211_BAND_ATTR_MAX, (struct nlattr *) nla_data(nl_band), |
|
|
|
nla_len(nl_band), NULL); |
|
|
|
|
|
|
|
QList<BandInfo> *bands = static_cast<QList<BandInfo>*>(callback->bands); |
|
|
|
QList<BandInfo> *bands = static_cast<QList<BandInfo>*>(callback->extra); |
|
|
|
BandInfo band; |
|
|
|
|
|
|
|
if(tb_band[NL80211_BAND_ATTR_HT_CAPA]) { |
|
|
|