From df53e1c1b77152107dc1f6f359b176e623b1bc15 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Tue, 27 Aug 2013 09:09:56 -0400 Subject: [PATCH] remove libnl-cli dependency from Interface class, working on other classes --- interface.cpp | 211 +++++++++++++++++++++++++++++++--------------- interface.h | 6 +- iptest/iptest.cpp | 4 +- neighbor.cpp | 30 +++++-- utils.cpp | 57 +++++++++++++ utils.h | 4 + 6 files changed, 232 insertions(+), 80 deletions(-) diff --git a/interface.cpp b/interface.cpp index 700f431..ed00d31 100644 --- a/interface.cpp +++ b/interface.cpp @@ -1,13 +1,13 @@ -// 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 +// 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 -#include -#include -#include #include +#include +#include +#include +#include #include #include @@ -32,8 +32,8 @@ m_index(-1) m_index = Utils::interfaceIndex(interface); } -void Interface::addAddress(QString addressStr) const { - struct nl_sock *sock; +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); @@ -49,30 +49,37 @@ void Interface::addAddress(QString addressStr) const { } } - sock = nl_cli_alloc_socket(); - nl_cli_connect(sock, NETLINK_ROUTE); + 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); - 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; + 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(bcast); + nl_addr_put(address); nl_socket_free(sock); - return; + return 1; } rtnl_addr_set_ifindex(addr, m_index); @@ -83,24 +90,34 @@ void Interface::addAddress(QString addressStr) const { 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); - - //struct nlmsghdr *hdr = nlmsg_hdr(result); - //nl_msg_dump(result, stderr); - nlmsg_free(result); nl_socket_free(sock); + + return 0; } -void Interface::deleteAddress(QString addressStr) const { - struct nl_sock *sock; +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); @@ -116,30 +133,38 @@ void Interface::deleteAddress(QString addressStr) const { } } - sock = nl_cli_alloc_socket(); - nl_cli_connect(sock, NETLINK_ROUTE); + 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); - 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; + 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(bcast); + nl_addr_put(address); nl_socket_free(sock); - return; + return 1; } rtnl_addr_set_ifindex(addr, m_index); @@ -150,54 +175,76 @@ void Interface::deleteAddress(QString addressStr) const { 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 add address" << std::endl; + 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); - - //struct nlmsghdr *hdr = nlmsg_hdr(result); - //nl_msg_dump(result, stderr); - nlmsg_free(result); nl_socket_free(sock); + + return 0; } -bool Interface::hasCarrier() { - struct rtnl_link *link; - struct nl_sock *sock; +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; - sock = nl_cli_alloc_socket(); - nl_cli_connect(sock, NETLINK_ROUTE); + 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); - if(rtnl_link_get_kernel(sock, 0, interface, &link) < 0) { - std::cerr << "error looking up interface" << std::endl; - } + carrier = flags & IFF_RUNNING; - unsigned int flags = rtnl_link_get_flags(link); + rtnl_link_put(link); + nl_socket_free(sock); - bool carrier = flags & IFF_RUNNING; + if(ok != NULL) { + *ok = true; + } - rtnl_link_put(link); - nl_socket_free(sock); + return carrier; + } + } + + if(ok != NULL) { + *ok = false; + } - return carrier; + return false; } QStringList Interface::addresses() const { - struct nl_sock *sock; - struct rtnl_addr *addr; - struct nl_cache *addr_cache, *link_cache; + 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)); @@ -206,17 +253,48 @@ QStringList Interface::addresses() const { params.dp_buf = buf; params.dp_buflen = BUFLEN; - char *ipInterface = strndup(interface, strlen(interface)); - char *family = const_cast("inet"); + if(!(sock = Utils::connect())) { + free(ipInterface); + return QStringList(); + } + + if(!(Utils::alloc_addr_cache(sock, &addr_cache))) { + free(ipInterface); + nl_socket_free(sock); + return QStringList(); + } - 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(); + if(!(Utils::alloc_link_cache(sock, &link_cache))) { + free(ipInterface); + nl_cache_free(addr_cache); + nl_socket_free(sock); + return QStringList(); + } - nl_cli_addr_parse_family(addr, family); - nl_cli_addr_parse_dev(addr, link_cache, ipInterface); + 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); @@ -243,29 +321,30 @@ QStringList Interface::addresses() const { } } - nl_object_free(OBJ_CAST(addr)); + free(ipInterface); + rtnl_addr_put(addr); nl_cache_free(addr_cache); nl_cache_free(link_cache); nl_socket_free(sock); - free(ipInterface); return addrsList; } QStringList Interface::list() { - struct nl_sock *sock; - struct nl_cache *link_cache; + struct nl_sock *sock = NULL; + struct nl_cache *link_cache = NULL; QStringList linkList; - sock = nl_cli_alloc_socket(); - nl_cli_connect(sock, NETLINK_ROUTE); + if(!(sock = Utils::connect())) { + 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; nl_socket_free(sock); - return linkList; + return QStringList(); } int index = 1; diff --git a/interface.h b/interface.h index bce66bc..0b5dc48 100644 --- a/interface.h +++ b/interface.h @@ -10,9 +10,9 @@ public: Interface(QString interface); static QStringList list(); QStringList addresses() const; - bool hasCarrier(); - void addAddress(QString address) const; - void deleteAddress(QString address) const; + bool hasCarrier(bool *ok = 0); + int addAddress(QString address) const; + int deleteAddress(QString address) const; const QString& name() const; private: diff --git a/iptest/iptest.cpp b/iptest/iptest.cpp index 8c56657..42c5587 100644 --- a/iptest/iptest.cpp +++ b/iptest/iptest.cpp @@ -8,10 +8,10 @@ int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); - Interface interface("enp0s25"); + Interface interface("enp0s3"); Neighbor neighbor; - std::cout << "MAC: " << qPrintable(neighbor.macOfIP("10.214.0.1")) << std::endl; + std::cout << "MAC: " << qPrintable(neighbor.macOfIP("10.0.4.1")) << std::endl; QStringList addresses = interface.addresses(); foreach(QString address, addresses) { diff --git a/neighbor.cpp b/neighbor.cpp index 9465c14..26fafaa 100644 --- a/neighbor.cpp +++ b/neighbor.cpp @@ -7,12 +7,14 @@ extern "C" { } #include "neighbor.h" +#include "utils.h" #include #include #define BUFLEN 65535 #define MACBUFLEN 18 #define IPBUFLEN 64 +#define EMPTY_MAC "00:00:00:00:00:00" Neighbor::Neighbor(QString interface) : QObject(0), @@ -22,9 +24,9 @@ m_interface(interface) } QString Neighbor::macOfIP(QString ip) const { - struct nl_sock *sock; - struct rtnl_neigh *neigh; - struct nl_cache *neigh_cache, *link_cache; + struct nl_sock *sock = NULL; + struct rtnl_neigh *neigh = NULL; + struct nl_cache *neigh_cache, *link_cache = NULL; struct nl_dump_params params; char buf[BUFLEN]; char mac[MACBUFLEN]; @@ -38,11 +40,21 @@ QString Neighbor::macOfIP(QString ip) const { params.dp_buf = buf; params.dp_buflen = BUFLEN; - sock = nl_cli_alloc_socket(); - nl_cli_connect(sock, NETLINK_ROUTE); - neigh_cache = nl_cli_neigh_alloc_cache(sock); - link_cache = nl_cli_link_alloc_cache(sock); - neigh = nl_cli_neigh_alloc(); + if(!(sock = Utils::connect())) { + return QString(EMPTY_MAC); + } + + if(!(Utils::alloc_neigh_cache(sock, &neigh_cache))) { + return QString(EMPTY_MAC); + } + + if(!(Utils::alloc_link_cache(sock, &link_cache))) { + return QString(EMPTY_MAC); + } + + if(!(neigh = rtnl_neigh_alloc())) { + return QString(EMPTY_MAC); + } if(!m_interface.isEmpty()) { QByteArray interfaceArray = m_interface.toLatin1(); @@ -79,7 +91,7 @@ QString Neighbor::macOfIP(QString ip) const { nl_socket_free(sock); if(mac == NULL || count == 0) { - return "00:00:00:00:00:00"; + return EMPTY_MAC; } QString macStr = mac; diff --git a/utils.cpp b/utils.cpp index 4b1a9c8..2048762 100644 --- a/utils.cpp +++ b/utils.cpp @@ -11,6 +11,63 @@ extern "C" { #include #include +struct nl_sock* Utils::connect() { + struct nl_sock *sock = nl_socket_alloc(); + int err = 0; + + if(sock == NULL) { + std::cerr << "could not allocate netlink socket" << std::endl; + return 0; + } + + 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 sock; +} + +int Utils::alloc_addr_cache(struct nl_sock *sock, struct nl_cache **cache) { + int err = 0; + + if((err = rtnl_addr_alloc_cache(sock, cache)) < 0) { + std::cerr << "could not allocate address cache: " << nl_geterror(err) << std::endl; + return 0; + } + + nl_cache_mngt_provide(*cache); + + return 0; +} + +int Utils::alloc_link_cache(struct nl_sock *sock, struct nl_cache **cache) { + int err = 0; + + 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; + } + + nl_cache_mngt_provide(*cache); + + return 0; +} + +int Utils::alloc_neigh_cache(struct nl_sock *sock, struct nl_cache **cache) { + int err = 0; + + if((err = rtnl_neigh_alloc_cache(sock, cache)) < 0) { + std::cerr << "could not allocate neighbor cache: " << nl_geterror(err) << std::endl; + return 0; + } + + nl_cache_mngt_provide(*cache); + + return 0; +} + int Utils::interfaceIndex(QString interface) { QByteArray array = interface.toLatin1(); diff --git a/utils.h b/utils.h index 503818b..655534d 100644 --- a/utils.h +++ b/utils.h @@ -8,6 +8,10 @@ Q_OBJECT public: static int interfaceIndex(QString interface); + static struct nl_sock* connect(); + static int alloc_addr_cache(struct nl_sock *sock, struct nl_cache **cache); + static int alloc_link_cache(struct nl_sock *sock, struct nl_cache **cache); + static int alloc_neigh_cache(struct nl_sock *sock, struct nl_cache **cache); }; #endif // LIBIP_UTILS_H