|
|
|
// gcc -Wall -Werror -O2 -s -pedantic-errors -std=gnu99 -I/usr/include/libnl3 -o nl-neigh-list nl-neigh-list.c -lnl-route-3 -lnl-3
|
|
|
|
// armeb-linux-gcc -Wall -Werror -O2 -s -std=gnu99 -I/usr/include/libnl3 -o nl-neigh-list nl-neigh-list.c -L. -lnl-route-3 -lnl-3 -lnl-nf-3 -lnl-genl-3
|
|
|
|
// with libs static compiled: armeb-linux-gcc -Wall -Werror -O2 -s -std=gnu99 -I/usr/include/libnl3 -o nl-neigh-list nl-neigh-list.c -L. -Wl,-Bstatic -lnl-route-3 -lnl-3 -lnl-nf-3 -lnl-genl-3 -Wl,-Bdynamic -lpthread -ldl -lm
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <netlink/socket.h>
|
|
|
|
#include <linux/netlink.h>
|
|
|
|
#include <netlink/netlink.h>
|
|
|
|
#include <netlink/route/addr.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "interface.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <QStringList>
|
|
|
|
#include <QTimer>
|
|
|
|
#include <QtCore/QCoreApplication>
|
|
|
|
#include <QDir>
|
|
|
|
#include <QtDebug>
|
|
|
|
|
|
|
|
#define BUFLEN 65535
|
|
|
|
#define ADDRBUFLEN BUFLEN
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\class Interface
|
|
|
|
\brief The Interface class is used to manage IP addresses associated with an interface.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Constructs an Interface object. All operations will be limited to the specified \a interface.
|
|
|
|
*/
|
|
|
|
Interface::Interface(QString interface) :
|
|
|
|
QObject(0),
|
|
|
|
m_interface(interface),
|
|
|
|
m_index(-1)
|
|
|
|
{
|
|
|
|
m_index = Utils::interfaceIndex(interface);
|
|
|
|
}
|
|
|
|
|
|
|
|
Interface::~Interface() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Set the interface's administrative link state to up. Requires that the CAP_NET_ADMIN capability be set on the application binary, or run as root (\a not \a recommended). Returns 0 on success, 1 on error.
|
|
|
|
*/
|
|
|
|
int Interface::setLinkUp() {
|
|
|
|
struct rtnl_link *link, *link_orig = NULL;
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
QByteArray interfaceArray = m_interface.toLatin1();
|
|
|
|
const char *interface = interfaceArray.constData();
|
|
|
|
|
|
|
|
if((sock = Utils::connect())) {
|
|
|
|
if(rtnl_link_get_kernel(sock, 0, interface, &link_orig) < 0) {
|
|
|
|
std::cerr << "error looking up interface" << std::endl;
|
|
|
|
nl_socket_free(sock);
|
|
|
|
}else{
|
|
|
|
if(!link_orig) {
|
|
|
|
std::cerr << "can't get link" << std::endl;
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
link = rtnl_link_alloc();
|
|
|
|
|
|
|
|
if(!link) {
|
|
|
|
std::cerr << "can't alloc link" << std::endl;
|
|
|
|
rtnl_link_put(link_orig);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
rtnl_link_set_flags(link, IFF_UP);
|
|
|
|
|
|
|
|
if((err = rtnl_link_change(sock, link_orig, link, 0)) < 0) {
|
|
|
|
//error = nl_geterror(err);
|
|
|
|
rtnl_link_put(link);
|
|
|
|
rtnl_link_put(link_orig);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_link_put(link);
|
|
|
|
rtnl_link_put(link_orig);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Set the interface's administrative link state to down. Requires that the CAP_NET_ADMIN capability be set on the application binary, or run as root (\a not \a recommended). Returns 0 on success, 1 on error.
|
|
|
|
*/
|
|
|
|
int Interface::setLinkDown() {
|
|
|
|
struct rtnl_link *link, *link_orig = NULL;
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
QByteArray interfaceArray = m_interface.toLatin1();
|
|
|
|
const char *interface = interfaceArray.constData();
|
|
|
|
|
|
|
|
if((sock = Utils::connect())) {
|
|
|
|
if(rtnl_link_get_kernel(sock, 0, interface, &link_orig) < 0) {
|
|
|
|
std::cerr << "error looking up interface" << std::endl;
|
|
|
|
nl_socket_free(sock);
|
|
|
|
}else{
|
|
|
|
if(!link_orig) {
|
|
|
|
std::cerr << "can't get link" << std::endl;
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
link = rtnl_link_alloc();
|
|
|
|
|
|
|
|
if(!link) {
|
|
|
|
std::cerr << "can't alloc link" << std::endl;
|
|
|
|
rtnl_link_put(link_orig);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
rtnl_link_unset_flags(link, IFF_UP);
|
|
|
|
|
|
|
|
if((err = rtnl_link_change(sock, link_orig, link, 0)) < 0) {
|
|
|
|
//error = nl_geterror(err);
|
|
|
|
rtnl_link_put(link);
|
|
|
|
rtnl_link_put(link_orig);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_link_put(link);
|
|
|
|
rtnl_link_put(link_orig);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Add an IP address to the interface using the CIDR notation, e.g. 192.168.1.1/24. Requires that the CAP_NET_ADMIN capability be set on the application binary, or run as root (\a not \a recommended). Returns 0 on success, 1 on error.
|
|
|
|
*/
|
|
|
|
int Interface::addAddress(QString addressStr) const {
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
QByteArray addressArrayNoMask = addressStr.left(addressStr.indexOf('/')).toLatin1();
|
|
|
|
QByteArray addressArray = addressStr.toLatin1();
|
|
|
|
QString bitmask = addressStr.right(2);
|
|
|
|
const char *addressDataNoMask = addressArrayNoMask.constData();
|
|
|
|
const char *addressData = addressArray.constData();
|
|
|
|
in_addr_t brdInt = inet_addr(addressDataNoMask);
|
|
|
|
struct in_addr brd = { .s_addr = brdInt };
|
|
|
|
int bitlen = bitmask.toInt();
|
|
|
|
|
|
|
|
if(bitlen <= 30) {
|
|
|
|
for(int i = 31; i >= bitlen; i--) {
|
|
|
|
brd.s_addr |= htonl(1 << (31 - i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(sock = Utils::connect())) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct rtnl_addr *addr = rtnl_addr_alloc();
|
|
|
|
|
|
|
|
if(!addr) {
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct nl_addr *address = NULL;
|
|
|
|
struct nl_addr *bcast = NULL;
|
|
|
|
struct nl_msg *result = NULL;
|
|
|
|
int parseResult = nl_addr_parse(addressData, AF_UNSPEC, &address);
|
|
|
|
|
|
|
|
if(parseResult != 0) {
|
|
|
|
std::cerr << "could not parse address" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int parseBroadcastResult = nl_addr_parse(inet_ntoa(brd), AF_INET, &bcast);
|
|
|
|
|
|
|
|
if(parseBroadcastResult != 0) {
|
|
|
|
std::cerr << "could not parse broadcast address" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_addr_set_ifindex(addr, m_index);
|
|
|
|
rtnl_addr_set_local(addr, address);
|
|
|
|
rtnl_addr_set_broadcast(addr, bcast);
|
|
|
|
|
|
|
|
int ret = rtnl_addr_build_add_request(addr, 0, &result);
|
|
|
|
|
|
|
|
if(ret != 0) {
|
|
|
|
std::cerr << "could not build add request" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_addr_put(bcast);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(rtnl_addr_add(sock, addr, 0) != 0) {
|
|
|
|
std::cerr << "could not add address" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_addr_put(bcast);
|
|
|
|
nlmsg_free(result);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_addr_put(bcast);
|
|
|
|
nlmsg_free(result);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Delete an IP address from the interface using the CIDR notation, e.g. 192.168.1.1/24. Requires that the CAP_NET_ADMIN capability be set on the application binary, or run as root (\a not \a recommended). Returns 0 on success, 1 on error.
|
|
|
|
*/
|
|
|
|
int Interface::deleteAddress(QString addressStr) const {
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
QByteArray addressArrayNoMask = addressStr.left(addressStr.indexOf('/')).toLatin1();
|
|
|
|
QByteArray addressArray = addressStr.toLatin1();
|
|
|
|
QString bitmask = addressStr.right(2);
|
|
|
|
const char *addressDataNoMask = addressArrayNoMask.constData();
|
|
|
|
const char *addressData = addressArray.constData();
|
|
|
|
in_addr_t brdInt = inet_addr(addressDataNoMask);
|
|
|
|
struct in_addr brd = { .s_addr = brdInt };
|
|
|
|
int bitlen = bitmask.toInt();
|
|
|
|
|
|
|
|
if(bitlen <= 30) {
|
|
|
|
for(int i = 31; i >= bitlen; i--) {
|
|
|
|
brd.s_addr |= htonl(1 << (31 - i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(sock = Utils::connect())) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct rtnl_addr *addr = rtnl_addr_alloc();
|
|
|
|
struct nl_addr *address = NULL;
|
|
|
|
struct nl_addr *bcast = NULL;
|
|
|
|
struct nl_msg *result = NULL;
|
|
|
|
|
|
|
|
if(!addr) {
|
|
|
|
std::cerr << "could not allocate address" << std::endl;
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int parseResult = nl_addr_parse(addressData, AF_UNSPEC, &address);
|
|
|
|
|
|
|
|
if(parseResult != 0) {
|
|
|
|
std::cerr << "could not parse address" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int parseBroadcastResult = nl_addr_parse(inet_ntoa(brd), AF_INET, &bcast);
|
|
|
|
|
|
|
|
if(parseBroadcastResult != 0) {
|
|
|
|
std::cerr << "could not parse broadcast address" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_addr_set_ifindex(addr, m_index);
|
|
|
|
rtnl_addr_set_local(addr, address);
|
|
|
|
rtnl_addr_set_broadcast(addr, bcast);
|
|
|
|
|
|
|
|
int ret = rtnl_addr_build_delete_request(addr, 0, &result);
|
|
|
|
|
|
|
|
if(ret != 0) {
|
|
|
|
std::cerr << "could not build add request" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_addr_put(bcast);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(rtnl_addr_delete(sock, addr, 0) != 0) {
|
|
|
|
std::cerr << "could not delete address" << std::endl;
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nlmsg_free(result);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_addr_put(bcast);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_addr_put(address);
|
|
|
|
nl_addr_put(bcast);
|
|
|
|
nlmsg_free(result);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns true if the interface is administratively up, otherwise false if it is administratively down or if there was an error retrieving the status information. If there was an error, *ok will be set to false, otherwise it will be true.
|
|
|
|
*/
|
|
|
|
bool Interface::hasAdminLink(bool *ok) {
|
|
|
|
struct rtnl_link *link = NULL;
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
QByteArray interfaceArray = m_interface.toLatin1();
|
|
|
|
const char *interface = interfaceArray.constData();
|
|
|
|
bool carrier = false;
|
|
|
|
|
|
|
|
if((sock = Utils::connect())) {
|
|
|
|
if(rtnl_link_get_kernel(sock, 0, interface, &link) < 0) {
|
|
|
|
std::cerr << "error looking up interface" << std::endl;
|
|
|
|
nl_socket_free(sock);
|
|
|
|
}else{
|
|
|
|
unsigned int flags = rtnl_link_get_flags(link);
|
|
|
|
|
|
|
|
carrier = (flags & IFF_UP) == IFF_UP;
|
|
|
|
|
|
|
|
rtnl_link_put(link);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
if(ok != NULL) {
|
|
|
|
*ok = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return carrier;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ok != NULL) {
|
|
|
|
*ok = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns true if the interface is up and running (link-layer is up), and false if the link/interface is down, or if there was an error retrieving the status information. If there was an error, *ok will be set to false, otherwise it will be true.
|
|
|
|
*/
|
|
|
|
bool Interface::hasCarrier(bool *ok) {
|
|
|
|
struct rtnl_link *link = NULL;
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
QByteArray interfaceArray = m_interface.toLatin1();
|
|
|
|
const char *interface = interfaceArray.constData();
|
|
|
|
bool carrier = false;
|
|
|
|
|
|
|
|
if((sock = Utils::connect())) {
|
|
|
|
if(rtnl_link_get_kernel(sock, 0, interface, &link) < 0) {
|
|
|
|
std::cerr << "error looking up interface" << std::endl;
|
|
|
|
nl_socket_free(sock);
|
|
|
|
}else{
|
|
|
|
unsigned int flags = rtnl_link_get_flags(link);
|
|
|
|
|
|
|
|
carrier = flags & IFF_RUNNING;
|
|
|
|
|
|
|
|
rtnl_link_put(link);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
if(ok != NULL) {
|
|
|
|
*ok = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return carrier;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ok != NULL) {
|
|
|
|
*ok = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns a list of assigned IP addresses on the interface. All addresses include the subnet mask as CIDR notation (e.g. 192.168.1.1/24).
|
|
|
|
*/
|
|
|
|
QStringList Interface::addresses() const {
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
struct rtnl_addr *addr = NULL;
|
|
|
|
struct nl_cache *addr_cache, *link_cache = NULL;
|
|
|
|
struct nl_dump_params params;
|
|
|
|
char buf[BUFLEN];
|
|
|
|
char addrs[ADDRBUFLEN];
|
|
|
|
QByteArray interfaceArray = m_interface.toLatin1();
|
|
|
|
const char *interface = interfaceArray.constData();
|
|
|
|
char *ipInterface = strndup(interface, strlen(interface));
|
|
|
|
|
|
|
|
memset(¶ms, 0, sizeof(struct nl_dump_params));
|
|
|
|
|
|
|
|
params.dp_type = NL_DUMP_LINE;
|
|
|
|
params.dp_fd = NULL;
|
|
|
|
params.dp_buf = buf;
|
|
|
|
params.dp_buflen = BUFLEN;
|
|
|
|
|
|
|
|
if(!(sock = Utils::connect())) {
|
|
|
|
free(ipInterface);
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Utils::alloc_addr_cache(sock, &addr_cache)) {
|
|
|
|
free(ipInterface);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Utils::alloc_link_cache(sock, &link_cache)) {
|
|
|
|
free(ipInterface);
|
|
|
|
nl_cache_free(addr_cache);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(addr = rtnl_addr_alloc())) {
|
|
|
|
std::cerr << "could not allocate address" << std::endl;
|
|
|
|
free(ipInterface);
|
|
|
|
nl_cache_free(addr_cache);
|
|
|
|
nl_cache_free(link_cache);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_addr_set_family(addr, AF_INET);
|
|
|
|
|
|
|
|
int ival = 0;
|
|
|
|
|
|
|
|
if(!(ival = rtnl_link_name2i(link_cache, ipInterface))) {
|
|
|
|
std::cerr << "Link " << ipInterface << " does not exist" << std::endl;
|
|
|
|
free(ipInterface);
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_cache_free(addr_cache);
|
|
|
|
nl_cache_free(link_cache);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_addr_set_ifindex(addr, ival);
|
|
|
|
|
|
|
|
memset(buf, 0, BUFLEN);
|
|
|
|
memset(addrs, 0, ADDRBUFLEN);
|
|
|
|
|
|
|
|
nl_cache_dump_filter(addr_cache, ¶ms, OBJ_CAST(addr));
|
|
|
|
|
|
|
|
buf[BUFLEN - 1] = '\0';
|
|
|
|
|
|
|
|
QString addrsString = buf;
|
|
|
|
QStringList addrsLines = addrsString.split('\n');
|
|
|
|
QStringList addrsList;
|
|
|
|
|
|
|
|
foreach(QString addrString, addrsLines) {
|
|
|
|
QStringList fields = addrString.split(' ');
|
|
|
|
|
|
|
|
if(fields.count() > 0) {
|
|
|
|
QString address = fields.at(0);
|
|
|
|
|
|
|
|
if(!address.isEmpty()) {
|
|
|
|
addrsList << fields.at(0);
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
std::cerr << "empty line: " << qPrintable(fields.join(' ')) << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(ipInterface);
|
|
|
|
rtnl_addr_put(addr);
|
|
|
|
nl_cache_free(addr_cache);
|
|
|
|
nl_cache_free(link_cache);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
return addrsList;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns a list of all interfaces on the system.
|
|
|
|
*/
|
|
|
|
QStringList Interface::list() {
|
|
|
|
struct nl_sock *sock = NULL;
|
|
|
|
struct nl_cache *link_cache = NULL;
|
|
|
|
QStringList linkList;
|
|
|
|
|
|
|
|
if(!(sock = Utils::connect())) {
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Utils::alloc_link_cache(sock, &link_cache)) {
|
|
|
|
nl_socket_free(sock);
|
|
|
|
return QStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
int index = 1;
|
|
|
|
|
|
|
|
forever {
|
|
|
|
struct rtnl_link *link = rtnl_link_get(link_cache, index);
|
|
|
|
|
|
|
|
if(link != NULL) {
|
|
|
|
char *name = rtnl_link_get_name(link);
|
|
|
|
|
|
|
|
linkList << name;
|
|
|
|
|
|
|
|
rtnl_link_put(link);
|
|
|
|
}else{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
++index;
|
|
|
|
}
|
|
|
|
|
|
|
|
nl_cache_free(link_cache);
|
|
|
|
nl_socket_free(sock);
|
|
|
|
|
|
|
|
// workaround for libnl issue: https://github.com/tgraf/libnl/issues/49
|
|
|
|
// find any interfaces libnl doesn't know about (e.g. USB wireless adapters after they've been unplugged and replugged)
|
|
|
|
QDir dir("/sys/class/net");
|
|
|
|
QStringList interfaces = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
|
|
|
|
foreach(QString interface, interfaces) {
|
|
|
|
if(!linkList.contains(interface)) {
|
|
|
|
linkList << interface;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
linkList.sort();
|
|
|
|
|
|
|
|
return linkList;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Returns the name of the interface used when the Interface object was constructed.
|
|
|
|
*/
|
|
|
|
const QString& Interface::name() const {
|
|
|
|
return m_interface;
|
|
|
|
}
|