You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
6.3 KiB

11 years ago
// 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 -lnl-cli-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-cli-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-cli-3 -lnl-nf-3 -lnl-genl-3 -Wl,-Bdynamic -lpthread -ldl -lm
extern "C" {
#include <netlink/cli/utils.h>
#include <netlink/cli/neigh.h>
#include <netlink/cli/addr.h>
#include <netlink/cli/link.h>
11 years ago
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
11 years ago
}
#include "interface.h"
#include <iostream>
#include <QStringList>
#include <QTimer>
#include <QtGui/QGuiApplication>
#define BUFLEN 65535
#define ADDRBUFLEN BUFLEN
11 years ago
Interface::Interface(QString interface) :
QObject(0),
m_interface(interface),
m_index(-1)
11 years ago
{
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);
}
void Interface::addAddress(QString addressStr) {
struct nl_sock *sock;
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));
}
}
sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
struct rtnl_addr *addr = rtnl_addr_alloc();
struct nl_addr *address = NULL;
struct nl_addr *bcast = NULL;
struct nl_msg *result = NULL;
int parseResult = nl_addr_parse(addressData, AF_UNSPEC, &address);
int parseBroadcastResult = nl_addr_parse(inet_ntoa(brd), AF_INET, &bcast);
if(parseResult != 0) {
std::cerr << "could not parse address" << std::endl;
rtnl_addr_put(addr);
nl_addr_put(bcast);
nl_socket_free(sock);
return;
}
if(parseBroadcastResult != 0) {
std::cerr << "could not parse broadcast address" << std::endl;
rtnl_addr_put(addr);
nl_addr_put(bcast);
nl_socket_free(sock);
return;
}
rtnl_addr_set_ifindex(addr, m_index);
rtnl_addr_set_local(addr, address);
rtnl_addr_set_broadcast(addr, bcast);
11 years ago
int ret = rtnl_addr_build_add_request(addr, 0, &result);
if(ret != 0) {
std::cerr << "could not build add request" << std::endl;
}
if(rtnl_addr_add(sock, addr, 0) != 0) {
std::cerr << "could not add address" << std::endl;
}
rtnl_addr_put(addr);
nl_addr_put(bcast);
//struct nlmsghdr *hdr = nlmsg_hdr(result);
//nl_msg_dump(result, stderr);
nlmsg_free(result);
nl_socket_free(sock);
11 years ago
}
bool Interface::hasCarrier() {
struct rtnl_link *link;
struct nl_sock *sock;
QByteArray interfaceArray = m_interface.toLatin1();
const char *interface = interfaceArray.constData();
sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
if(rtnl_link_get_kernel(sock, 0, interface, &link) < 0) {
std::cerr << "error looking up interface" << std::endl;
}
unsigned int flags = rtnl_link_get_flags(link);
bool carrier = flags & IFF_RUNNING;
rtnl_link_put(link);
nl_socket_free(sock);
return carrier;
}
QStringList Interface::addresses() {
struct nl_sock *sock;
struct rtnl_addr *addr;
struct nl_cache *addr_cache, *link_cache;
struct nl_dump_params params;
char buf[BUFLEN];
char addrs[ADDRBUFLEN];
QByteArray interfaceArray = m_interface.toLatin1();
const char *interface = interfaceArray.constData();
memset(&params, 0, sizeof(struct nl_dump_params));
params.dp_type = NL_DUMP_LINE;
params.dp_fd = NULL;
params.dp_buf = buf;
params.dp_buflen = BUFLEN;
char *ipInterface = strndup(interface, strlen(interface));
char *family = const_cast<char*>("inet");
sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
addr_cache = nl_cli_addr_alloc_cache(sock);
link_cache = nl_cli_link_alloc_cache(sock);
addr = nl_cli_addr_alloc();
nl_cli_addr_parse_family(addr, family);
nl_cli_addr_parse_dev(addr, link_cache, ipInterface);
memset(buf, 0, BUFLEN);
memset(addrs, 0, ADDRBUFLEN);
nl_cache_dump_filter(addr_cache, &params, 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;
}
}
nl_object_free(OBJ_CAST(addr));
nl_cache_free(addr_cache);
nl_cache_free(link_cache);
nl_socket_free(sock);
free(ipInterface);
return addrsList;
}
QStringList Interface::list() {
11 years ago
struct nl_sock *sock;
struct nl_cache *link_cache;
QStringList linkList;
11 years ago
sock = nl_cli_alloc_socket();
nl_cli_connect(sock, NETLINK_ROUTE);
int ret = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache);
11 years ago
if(ret != 0) {
std::cerr << "could not allocate link cache" << std::endl;
nl_socket_free(sock);
return linkList;
}
11 years ago
int index = 1;
11 years ago
forever {
struct rtnl_link *link = rtnl_link_get(link_cache, index);
11 years ago
if(link != NULL) {
char *name = rtnl_link_get_name(link);
11 years ago
linkList << name;
rtnl_link_put(link);
}else{
rtnl_link_put(link);
break;
11 years ago
}
++index;
11 years ago
}
nl_cache_free(link_cache);
11 years ago
nl_socket_free(sock);
return linkList;
11 years ago
}