Skip to content

Commit

Permalink
File NetlinkCalls added
Browse files Browse the repository at this point in the history
  • Loading branch information
pawsten committed Oct 4, 2023
1 parent be6dee2 commit b43731b
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 85 deletions.
1 change: 1 addition & 0 deletions libebpfdiscovery/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ list(
src/Config.cpp
src/Discovery.cpp
src/IpAddressChecker.cpp
src/NetlinkCalls.cpp
src/Session.cpp
src/StringFunctions.cpp
)
Expand Down
12 changes: 1 addition & 11 deletions libebpfdiscovery/headers/ebpfdiscovery/IpAddressChecker.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstdint>
#include <stddef.h>
#include "ebpfdiscovery/NetlinkCalls.h"
#include <initializer_list>
#include <vector>

struct sockaddr_nl;

namespace ebpfdiscovery {

Expand All @@ -19,13 +17,6 @@ struct IpIfce {
bool isLocalBridge;
};

class NetlinkCalls {
public:
virtual int sendIpAddrRequest(int fd, sockaddr_nl* dst, int domain) const;
virtual int sendBridgesRequest(int fd, sockaddr_nl* dst, int domain) const;
virtual int receive(int fd, sockaddr_nl* dst, void* buf, size_t len) const;
};

class IpAddressChecker {
std::vector<IpIfce> interfaces;
std::vector<IpIfce>::iterator bridgeEnd = interfaces.end();
Expand All @@ -44,6 +35,5 @@ class IpAddressChecker {
bool isAddressExternalLocal(IPv4 addr);
bool readNetworks();
};

} // namespace ebpfdiscovery

17 changes: 17 additions & 0 deletions libebpfdiscovery/headers/ebpfdiscovery/NetlinkCalls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstdint>
#include <stddef.h>

struct sockaddr_nl;

namespace ebpfdiscovery {

class NetlinkCalls {
public:
virtual int sendIpAddrRequest(int fd, sockaddr_nl* dst, int domain) const;
virtual int sendBridgesRequest(int fd, sockaddr_nl* dst, int domain) const;
virtual int receive(int fd, sockaddr_nl* dst, void* buf, size_t len) const;
};
} // namespace ebpfdiscovery

74 changes: 0 additions & 74 deletions libebpfdiscovery/src/IpAddressChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <gsl/util>
#include <iostream>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <string>
#include <string_view>
#include <unistd.h>
Expand All @@ -31,20 +30,6 @@ static void logErrorFromErrno(std::string_view prefix) {
}


static void addNetlinkMsg(nlmsghdr* nh, int type, const void* data, int dataLen) {
struct rtattr* rta;
int rta_length = RTA_LENGTH(dataLen);

rta = reinterpret_cast<rtattr*>((char*)nh + NLMSG_ALIGN(nh->nlmsg_len));

rta->rta_type = type;
rta->rta_len = rta_length;
nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta_length);

memcpy(RTA_DATA(rta), data, dataLen);
}


static ebpfdiscovery::IpIfce parseIfceIPv4(void* data, size_t len) {
ebpfdiscovery::IpIfce ifce{};
ifaddrmsg* ifa = reinterpret_cast<ifaddrmsg*>(data);
Expand Down Expand Up @@ -82,65 +67,6 @@ static int getIfIndex(void* data) {

namespace ebpfdiscovery {

int NetlinkCalls::sendIpAddrRequest(int fd, sockaddr_nl* dst, int domain) const{
std::array<char, BUFFLEN> buf{};

nlmsghdr* nl;
nl = reinterpret_cast<nlmsghdr*>(buf.data());
nl->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
nl->nlmsg_type = RTM_GETADDR;
nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;

ifaddrmsg* ifa;
ifa = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(nl));
ifa->ifa_family = domain; // ipv4 or ipv6

iovec iov = {nl, nl->nlmsg_len};
msghdr msg = {dst, sizeof(*dst), &iov, 1, NULL, 0, 0};

return sendmsg(fd, &msg, 0);
}

int NetlinkCalls::sendBridgesRequest(int fd, sockaddr_nl* dst, int domain) const{
struct {
struct nlmsghdr n;
struct ifinfomsg i;
char _[1024]; // space for rtattr array
} r{};

const char* dev_type = "bridge";

r.n.nlmsg_len = NLMSG_LENGTH(sizeof(ifinfomsg));
r.n.nlmsg_type = RTM_GETLINK;
r.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
r.i.ifi_family = AF_PACKET;
r.n.nlmsg_pid = 0;
r.n.nlmsg_seq = 0;

rtattr* linkinfo = reinterpret_cast<rtattr*>((char*)&r.n + NLMSG_ALIGN(r.n.nlmsg_len));
addNetlinkMsg(&r.n, IFLA_LINKINFO, NULL, 0);
addNetlinkMsg(&r.n, IFLA_INFO_KIND, dev_type, strlen(dev_type) + 1);
linkinfo->rta_len = (int)(reinterpret_cast<char*>(&r.n) + NLMSG_ALIGN(r.n.nlmsg_len) - reinterpret_cast<char*>(linkinfo));

iovec iov = {&r.n, r.n.nlmsg_len};
msghdr msg = {dst, sizeof(*dst), &iov, 1, NULL, 0, 0};

return sendmsg(fd, &msg, 0);
}

int NetlinkCalls::receive(int fd, sockaddr_nl* dst, void* buf, size_t len) const {
iovec iov;
msghdr msg {};
iov.iov_base = buf;
iov.iov_len = len;

msg.msg_name = dst;
msg.msg_namelen = sizeof(*dst);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

return recvmsg(fd, &msg, 0);
}

IpAddressChecker::IpAddressChecker(std::initializer_list<IpIfce> config, const NetlinkCalls &calls) :netlink(calls) {
interfaces.insert(interfaces.end(), config.begin(), config.end());
Expand Down
84 changes: 84 additions & 0 deletions libebpfdiscovery/src/NetlinkCalls.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "ebpfdiscovery/NetlinkCalls.h"
#include <arpa/inet.h>
#include <array>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <cstring>

namespace ebpfdiscovery {

static constexpr uint32_t BUFFLEN{4096};

static void addNetlinkMsg(nlmsghdr* nh, int type, const void* data, int dataLen) {
struct rtattr* rta;
int rta_length = RTA_LENGTH(dataLen);

rta = reinterpret_cast<rtattr*>((char*)nh + NLMSG_ALIGN(nh->nlmsg_len));

rta->rta_type = type;
rta->rta_len = rta_length;
nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta_length);

memcpy(RTA_DATA(rta), data, dataLen);
}

int NetlinkCalls::sendIpAddrRequest(int fd, sockaddr_nl* dst, int domain) const {
std::array<char, BUFFLEN> buf{};

nlmsghdr* nl;
nl = reinterpret_cast<nlmsghdr*>(buf.data());
nl->nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg));
nl->nlmsg_type = RTM_GETADDR;
nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;

ifaddrmsg* ifa;
ifa = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(nl));
ifa->ifa_family = domain; // ipv4 or ipv6

iovec iov = {nl, nl->nlmsg_len};
msghdr msg = {dst, sizeof(*dst), &iov, 1, NULL, 0, 0};

return sendmsg(fd, &msg, 0);
}

int NetlinkCalls::sendBridgesRequest(int fd, sockaddr_nl* dst, int domain) const {
struct {
struct nlmsghdr n;
struct ifinfomsg i;
char _[1024]; // space for rtattr array
} r{};

const char* dev_type = "bridge";

r.n.nlmsg_len = NLMSG_LENGTH(sizeof(ifinfomsg));
r.n.nlmsg_type = RTM_GETLINK;
r.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
r.i.ifi_family = AF_PACKET;
r.n.nlmsg_pid = 0;
r.n.nlmsg_seq = 0;

rtattr* linkinfo = reinterpret_cast<rtattr*>((char*)&r.n + NLMSG_ALIGN(r.n.nlmsg_len));
addNetlinkMsg(&r.n, IFLA_LINKINFO, NULL, 0);
addNetlinkMsg(&r.n, IFLA_INFO_KIND, dev_type, strlen(dev_type) + 1);
linkinfo->rta_len = (int)(reinterpret_cast<char*>(&r.n) + NLMSG_ALIGN(r.n.nlmsg_len) - reinterpret_cast<char*>(linkinfo));

iovec iov = {&r.n, r.n.nlmsg_len};
msghdr msg = {dst, sizeof(*dst), &iov, 1, NULL, 0, 0};

return sendmsg(fd, &msg, 0);
}

int NetlinkCalls::receive(int fd, sockaddr_nl* dst, void* buf, size_t len) const {
iovec iov;
msghdr msg{};
iov.iov_base = buf;
iov.iov_len = len;

msg.msg_name = dst;
msg.msg_namelen = sizeof(*dst);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

return recvmsg(fd, &msg, 0);
}
} // namespace ebpfdiscovery

0 comments on commit b43731b

Please sign in to comment.