diff --git a/CMakeLists.txt b/CMakeLists.txt index f287728..b27af8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,25 +1,21 @@ cmake_minimum_required(VERSION 3.0) -project(macNock C CXX) +project(macNock C) option(MACNOCK_DEBUG "Enable debug messages" OFF) -if(CMAKE_COMPILER_IS_GNUCXX) - add_definitions(-Wall -Wpedantic -Wextra -std=c++11) -endif() +add_definitions(-Wall -Wextra -pedantic) if(MACNOCK_DEBUG) add_definitions(-DDEBUG) endif(MACNOCK_DEBUG) set(MACNOCK_SRC - main.cpp - macnockserver.cpp - macnockclient.cpp - nockpackage.cpp - mac.cpp - tc.cpp - log.cpp + main.c + macnockserver.c + macnockclient.c + tc.c + macstorage.c ) add_executable(macnock ${MACNOCK_SRC}) diff --git a/log.cpp b/log.cpp deleted file mode 100644 index 00eba8d..0000000 --- a/log.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "log.h" - -#include -#include - -namespace log { - -std::mutex g_output_mutex; - -#ifdef DEBUG -void debug(const std::string &dbg) -{ - std::lock_guard guard(g_output_mutex); - std::cout << dbg << std::endl; -} -#else -void debug(const std::string &) -{ - -} -#endif - -void error(const std::string &dbg) -{ - std::lock_guard guard(g_output_mutex); - std::cerr << dbg << std::endl; -} - -} // namespace log diff --git a/log.h b/log.h index dce0af9..c73461f 100644 --- a/log.h +++ b/log.h @@ -1,14 +1,12 @@ #ifndef _DEBUG_H #define _DEBUG_H -#include +#ifdef DEBUG +#include -namespace log { - -void debug(const std::string &dbg); - -void error(const std::string &dbg); - -} // namespace log +#define log_debug(...) printf(__VA_ARGS__) +#else +#define log_debug(...) do { } while (0); +#endif #endif // _DEBUG_H diff --git a/mac.cpp b/mac.cpp deleted file mode 100644 index 93ab0cb..0000000 --- a/mac.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "mac.h" - -#include -#include - -std::string to_string(const Mac &o) -{ - std::ostringstream stream; - for (Mac::const_iterator it=o.begin(); it!=o.end(); ++it) - { - stream << std::hex << std::setw(2) << std::setfill('0') << static_cast(*it); - } - return stream.str(); -} diff --git a/mac.h b/mac.h deleted file mode 100644 index 4944448..0000000 --- a/mac.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _MAC_H -#define _MAC_H - -#include -#include -#include - -using Mac = std::array; -using MacList = std::list; - -std::string to_string(const Mac &o); - -#endif // _MAC_H diff --git a/macnockclient.c b/macnockclient.c new file mode 100644 index 0000000..0f2ebdc --- /dev/null +++ b/macnockclient.c @@ -0,0 +1,108 @@ +#include "macnockclient.h" +#include "nockpackage.h" +#include "log.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const char *g_hood; +extern const char *g_interface; + +extern const int PORT; +extern const uint8_t VERSION; + +static uint8_t stop; + +void macNockClient_stop() +{ + log_debug("Stopping Client\n"); + stop = 1; +} + +void macNockClient_run() +{ + stop = 0; + + const char host[] = "ff02::1"; + + int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) + { + perror("[c] ERROR: Can't create socket"); + return; + } + + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, g_interface, strlen(g_interface)) < 0) + { + perror("[c] WARNING: Can't bind to device"); + } + + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, g_interface, IFNAMSIZ); + + if (!((ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) && (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0))) + { + perror("[c] ERROR: Can't read MAC"); + close(fd); + return; + } + + struct sockaddr_in6 servaddr; + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin6_family = AF_INET6; + servaddr.sin6_port = htons(PORT); + + if (inet_pton(AF_INET6, host, &servaddr.sin6_addr) == 0) + { + perror("[c] ERROR: Can't resolve host"); + close(fd); + return; + } + + const size_t hoodLen = strlen(g_hood)+1; + struct NockPackage *nock = malloc(sizeof(struct NockPackage) + hoodLen); + memcpy(nock->mac, ifr.ifr_hwaddr.sa_data, sizeof(nock->mac)); + nock->version = VERSION; + nock->hoodLen = hoodLen; + strcpy(nock->hood, g_hood); + const size_t len = sizeof(struct NockPackage) + hoodLen; + + while (!stop) + { + log_debug("[c] sending\n"); + + int sent = sendto(fd, nock, len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); + if (sent == -1) + { + perror("[c] ERROR: Can't send data"); + } + else if ((size_t)sent != len) + { + perror("[c] ERROR: Can't send all data"); + } + + usleep(1 * 1000 * 1000); // sleep 1 s + } + + free(nock); + + close(fd); + + log_debug("Client closed\n"); + return; +} diff --git a/macnockclient.cpp b/macnockclient.cpp deleted file mode 100644 index be072a0..0000000 --- a/macnockclient.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "macnockclient.h" -#include "nockpackage.h" -#include "log.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -macNockClient::macNockClient(const std::string &interface, const std::string &hood) - : m_interface(interface) - , m_hood(hood) -{ - -} - -void macNockClient::stop() -{ - log::debug("Stopping Client"); - m_stop = true; -} - -bool macNockClient::run() -{ - const std::string host{"ff02::1"}; - - m_stop = false; - - int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (fd < 0) - { - log::error(std::string("[c] ERROR: Can't create socket (") + strerror(errno) + ")."); - return false; - } - - if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, m_interface.c_str(), m_interface.size()) < 0) - { - log::error(std::string("[c] WARNING: Can't bind to device (") + strerror(errno) + ")."); - } - - ifreq ifr; - memset(&ifr, 0, sizeof(ifreq)); - strncpy(ifr.ifr_name, m_interface.c_str(), IFNAMSIZ); - - if (!((ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) && (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0))) - { - log::error(std::string("[c] ERROR: Can't read MAC (") + strerror(errno) + ")."); - return false; - } - - sockaddr_in6 servaddr; - memset(&servaddr, 0, sizeof(sockaddr_in6)); - servaddr.sin6_family = AF_INET6; - servaddr.sin6_port = htons(PORT); - - if (inet_pton(AF_INET6, host.c_str(), &servaddr.sin6_addr) == 0) - { - log::error(std::string("[c] ERROR: Can't resolve host (") + strerror(errno) + ")."); - close(fd); - return false; - } - - const Mac mac{ static_cast(ifr.ifr_hwaddr.sa_data[0]), static_cast(ifr.ifr_hwaddr.sa_data[1]), - static_cast(ifr.ifr_hwaddr.sa_data[2]), static_cast(ifr.ifr_hwaddr.sa_data[3]), - static_cast(ifr.ifr_hwaddr.sa_data[4]), static_cast(ifr.ifr_hwaddr.sa_data[5]), }; - const NockPackage nock{mac, m_hood}; - - while (!m_stop) - { - log::debug("[c] sending"); - uint8_t buf[256]; - size_t len = nock.serialize(buf, 256); - - int sent = sendto(fd, buf, len, 0, reinterpret_cast(&servaddr), sizeof(servaddr)); - if (sent == -1) - { - log::error(std::string("[c] ERROR: Can't send data (") + strerror(errno) + ")."); - } - else if (static_cast(sent) != len) - { - log::error("[c] ERROR: Can't send all data."); - } - - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - close(fd); - - log::debug("Client closed"); - return true; -} diff --git a/macnockclient.h b/macnockclient.h index f7ca82d..da6269c 100644 --- a/macnockclient.h +++ b/macnockclient.h @@ -1,16 +1,7 @@ -#include +#ifndef _MACNOCKCLIENT_H +#define _MACNOCKCLIENT_H -class macNockClient -{ -public: - macNockClient(const std::string &interface, const std::string &code); - bool run(); - void stop(); +void macNockClient_stop(); +void macNockClient_run(); -private: - -private: - const std::string &m_interface; - const std::string &m_hood; - bool m_stop; -}; +#endif // _MACNOCKCLIENT_H diff --git a/macnockserver.c b/macnockserver.c new file mode 100644 index 0000000..865ba83 --- /dev/null +++ b/macnockserver.c @@ -0,0 +1,118 @@ +#include "macnockserver.h" +#include "macstorage.h" +#include "nockpackage.h" +#include "log.h" +#include "tc.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern const char *g_hood; +extern const char *g_interface; + +extern const int PORT; +extern const uint8_t VERSION; + +static uint8_t stop; +int fd; + +void macNockServer_stop() +{ + log_debug("Stopping Server\n"); + stop = 1; + shutdown(fd, SHUT_RDWR); +} + +void macNockServer_run() +{ + stop = 0; + + tc_start(); + + fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + + if (fd < 0) + { + perror("[s] ERROR: Can't create socket"); + return; + } + + // allow to reuse the port immediately as soon as the service exits. + int sockoptval = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int)) != 0) + { + perror("[s] WARNING: Can't set socket options"); + } + + struct sockaddr_in6 my_addr; + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin6_family = AF_INET6; + my_addr.sin6_port = htons(PORT); + my_addr.sin6_addr = in6addr_any; + + if (bind(fd, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) + { + perror("[s] ERROR: Can't bind to address"); + return; + } + + while (!stop) + { + log_debug("[s] waiting for connection\n"); + + struct sockaddr_in6 client_addr; + socklen_t addrlen = sizeof(client_addr); + + static const size_t BUFSIZE = 2048; + uint8_t buf[BUFSIZE]; + + int recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&client_addr, &addrlen); + + if (recvlen <= 0) + { + continue; + } + + char addrBuf[INET6_ADDRSTRLEN]; + const char *ret = inet_ntop(AF_INET6, &client_addr.sin6_addr, addrBuf, sizeof(addrBuf)); + log_debug("[s] received %d bytes from %s\n", recvlen, ret); + + struct NockPackage *nock = (struct NockPackage *)buf; + nock->hood[nock->hoodLen] = '\0'; + + if (nock->version != VERSION) + { + fprintf(stderr, "Received package with wrong version from %s\n", ret); + continue; + } + + log_debug("The MAC: %2x:%2x:%2x:%2x:%2x:%2x, the Hood: %s\n", + nock->mac[0], nock->mac[1], nock->mac[2], nock->mac[3], nock->mac[4], nock->mac[5], nock->hood); + + if (strcmp(nock->hood, g_hood) == 0) + { + log_debug("[s] allowing %2x:%2x:%2x:%2x:%2x:%2x\n", + nock->mac[0], nock->mac[1], nock->mac[2], nock->mac[3], nock->mac[4], nock->mac[5]); + macStorage_add(nock->mac); + } + else + { + log_debug("[s] wrong hood. Not allowing %2x:%2x:%2x:%2x:%2x:%2x\n", + nock->mac[0], nock->mac[1], nock->mac[2], nock->mac[3], nock->mac[4], nock->mac[5]); + } + } + + close(fd); + tc_stop(); + + log_debug("Server closed\n"); + return; +} diff --git a/macnockserver.cpp b/macnockserver.cpp deleted file mode 100644 index ffc6805..0000000 --- a/macnockserver.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "macnockserver.h" -#include "nockpackage.h" -#include "log.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -macNockServer::macNockServer(const std::string &interface, const std::string &hood) - : m_interface(interface) - , m_hood(hood) - , m_stop(false) - , m_tc(interface) -{ - -} - -bool macNockServer::run() -{ - m_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - - if (m_sock < 0) - { - log::error(std::string("[s] ERROR: Can't create socket (") + strerror(errno) + ")."); - return false; - } - - // allow to reuse the port immediately as soon as the service exits. - int sockoptval = 1; - if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int)) != 0) - { - log::error(std::string("[s] WARNING: Can't set socket options (") + strerror(errno) + ")."); - } - - sockaddr_in6 my_addr; - memset(&my_addr, 0, sizeof(sockaddr_in6)); - my_addr.sin6_family = AF_INET6; - my_addr.sin6_port = htons(PORT); - my_addr.sin6_addr = in6addr_any; - - if (bind(m_sock, reinterpret_cast(&my_addr), sizeof(sockaddr_in6)) < 0) - { - log::error(std::string("[s] ERROR: Can't bind to address (") + strerror(errno) + ")"); - return false; - } - - while (!m_stop) - { - log::debug(std::string("[s] waiting on port ") + std::to_string(PORT)); - - sockaddr_in6 client_addr; - socklen_t addrlen = sizeof(client_addr); - - static const size_t BUFSIZE = 2048; - uint8_t buf[BUFSIZE]; - - int recvlen = recvfrom(m_sock, buf, BUFSIZE, 0, reinterpret_cast(&client_addr), &addrlen); - - if (recvlen <= 0) - { - continue; - } - - char addrBuf[INET6_ADDRSTRLEN]; - const char *ret = inet_ntop(AF_INET6, &client_addr.sin6_addr, addrBuf, sizeof(addrBuf)); - log::debug(std::string("[s] received ") + std::to_string(recvlen) + " bytes from " + ret); - - NockPackage nock; - if (nock.deserialize(buf, recvlen)) - { - const std::string mac{to_string(nock.getMac())}; - log::debug(std::string("The MAC: ") + mac + ", the Hood: " + nock.getHood()); - - if (nock.getHood() == m_hood) - { - log::debug(std::string("[s] allowing ") + mac); - MacList::iterator found = std::find(m_filterList.begin(), m_filterList.end(), nock.getMac()); - if (found == m_filterList.end()) - { - m_filterList.push_back(nock.getMac()); - m_tc.allow_mac(mac); - } - } - else - { - log::debug(std::string("[s] not allowing ") + mac + ", wrong hood"); - MacList::iterator found = std::remove(m_filterList.begin(), m_filterList.end(), nock.getMac()); - if (found != m_filterList.end()) - { - m_filterList.erase(found); - m_tc.disallow_mac(mac); - } - } - } - else - { - log::error(std::string("[s] can't deserialize message \"") + std::string(buf, buf+recvlen) + "\""); - } - } - - close(m_sock); - log::debug("Server closed"); - return true; -} - -void macNockServer::stop() -{ - log::debug("Stopping Server"); - m_stop = true; - shutdown(m_sock, SHUT_RDWR); -} diff --git a/macnockserver.h b/macnockserver.h index 40b6951..2dc277c 100644 --- a/macnockserver.h +++ b/macnockserver.h @@ -1,24 +1,9 @@ +#ifndef _MACNOCKSERVER_H +#define _MACNOCKSERVER_H + #include "tc.h" -#include "mac.h" -#include -#include +void macNockServer_stop(); +void macNockServer_run(); -class macNockServer -{ -public: - macNockServer(const std::string &interface, const std::string &hood); - bool run(); - void stop(); - -private: - void sendData(const int socket, const std::string &data) const; - -private: - const std::string &m_interface; - const std::string &m_hood; - bool m_stop; - int m_sock; - tc m_tc; - MacList m_filterList; -}; +#endif // _MACNOCKSERVER_H diff --git a/macstorage.c b/macstorage.c new file mode 100644 index 0000000..e88e460 --- /dev/null +++ b/macstorage.c @@ -0,0 +1,91 @@ +#include "macstorage.h" +#include "log.h" +#include "tc.h" + +#include +#include +#include +#include +#include + +static uint8_t stop; + +#define MAXENTRIES 30 + +struct Entry +{ + uint8_t mac[6]; + time_t timestamp; +} storage[MAXENTRIES]; + +size_t count = 0; + +pthread_mutex_t mux; + +void _addEntry(uint8_t mac[6]) +{ + for (size_t i=0; i + +void macStorage_add(uint8_t mac[]); +void macStorage_stop(); +void macStorage_run(); + +#endif // _MACSTORAGE_H diff --git a/main.c b/main.c new file mode 100644 index 0000000..f37ba8b --- /dev/null +++ b/main.c @@ -0,0 +1,108 @@ +#include "macnockserver.h" +#include "macnockclient.h" +#include "macstorage.h" +#include "log.h" + +#include +#include +#include +#include +#include + +const int PORT = 2342; +const uint8_t VERSION = 1; + +const char *g_interface; +const char *g_hood; + +void sigHandler(int sig) +{ + (void)sig; + macNockServer_stop(); + macNockClient_stop(); + macStorage_stop(); +} + +void* serverRoutine(void *arg) +{ + macNockServer_run(); + return arg; +} + +void* clientRoutine(void *arg) +{ + macNockClient_run(); + return arg; +} + +void* storageRoutine(void *arg) +{ + macStorage_run(); + return arg; +} + +int main(int argc, char *argv[]) +{ + if (argc < 3) + { + printf("Send and listen for nock requests\n"); + printf("\n"); + printf("%s interface code command\n", argv[0]); + printf("Example:\n"); + printf("%s eth0.3 \"FuerthV2\"\n", argv[0]); + return -1; + } + + g_interface = argv[1]; + g_hood = argv[2]; + + //log_debug("Running for hood %s (%s) on interface %s (%s)\n", g_hood, argv[1], g_interface, argv[2]); + + signal(SIGINT, &sigHandler); + signal(SIGTERM, &sigHandler); + + pthread_t serverThread; + pthread_t clientThread; + pthread_t storageThread; + + if (pthread_create(&serverThread, NULL, serverRoutine, NULL)) + { + fprintf(stderr, "Error creating thread\n"); + return 1; + } + + if (pthread_create(&clientThread, NULL, clientRoutine, NULL)) + { + fprintf(stderr, "Error creating thread\n"); + return 1; + } + + if (pthread_create(&storageThread, NULL, storageRoutine, NULL)) + { + fprintf(stderr, "Error creating thread\n"); + return 1; + } + + if (pthread_join(serverThread, NULL)) + { + fprintf(stderr, "Error joining thread\n"); + return 2; + } + + if (pthread_join(clientThread, NULL)) + { + fprintf(stderr, "Error joining thread\n"); + return 2; + } + + if (pthread_join(storageThread, NULL)) + { + fprintf(stderr, "Error joining thread\n"); + return 2; + } + + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + + return 0; +} diff --git a/main.cpp b/main.cpp deleted file mode 100644 index e95e078..0000000 --- a/main.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "macnockserver.h" -#include "macnockclient.h" -#include -#include -#include -#include -#include -#include - -macNockServer *server = nullptr; -macNockClient *client = nullptr; - -void sigHandler(int) -{ - if (server) - { - server->stop(); - } - if (client) - { - client->stop(); - } -} - -int main(int argc, char *argv[]) -{ - if (argc < 3) - { - std::cout << "Send and listen for nock requests" << std::endl; - std::cout << std::endl; - std::cout << argv[0] << " interface code command" << std::endl; - std::cout << "Example:" << std::endl; - std::cout << argv[0] << " eth0.3 \"FuerthV2\"" << std::endl; - return -1; - } - - const std::string interface{argv[1]}; - const std::string hood{argv[2]}; - - server = new macNockServer{interface, hood}; - client = new macNockClient{interface, hood}; - - signal(SIGINT, &sigHandler); - signal(SIGTERM, &sigHandler); - - std::thread serverThread{[](){server->run();}}; - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - - std::thread clientThread{[](){client->run();}}; - - serverThread.join(); - clientThread.join(); - - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - - delete client; - client = nullptr; - - delete server; - server = nullptr; - - return 0; -} diff --git a/nockpackage.cpp b/nockpackage.cpp deleted file mode 100644 index 5dd9160..0000000 --- a/nockpackage.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "nockpackage.h" - -#include - -NockPackage::NockPackage() -{ - -} - -NockPackage::NockPackage(const Mac &sourceMac, const Hood &hoodName) - : m_sourceMac(sourceMac) - , m_hoodName(hoodName) -{ - -} - -size_t NockPackage::serialize(uint8_t *buf, size_t maxlen) const -{ - uint8_t *target = buf; - if (maxlen < (m_sourceMac.size() + 1)) - return 0; - - *target = VERSION; - target++; - - for (Mac::const_iterator it=m_sourceMac.begin(); it!=m_sourceMac.end(); ++it) - { - *target = *it; - target++; - } - - for (Hood::const_iterator it=m_hoodName.begin(); it!=m_hoodName.end(); ++it) - { - *target = *it; - target++; - } - - return target-buf; -} - -bool NockPackage::deserialize(const uint8_t *buf, size_t len) -{ - const uint8_t *source = buf; - - if (len < (m_sourceMac.size() + 1)) - { - return false; - } - - if (*source != VERSION) - { - return false; - } - source++; - - for (Mac::iterator it=m_sourceMac.begin(); it!=m_sourceMac.end(); ++it) - { - *it = *source; - source++; - } - - m_hoodName = std::string(source, buf+len); - - return true; -} - -Mac NockPackage::getMac() const -{ - return m_sourceMac; -} - -std::string NockPackage::getHood() const -{ - return m_hoodName; -} diff --git a/nockpackage.h b/nockpackage.h index 85bc735..9d0a8db 100644 --- a/nockpackage.h +++ b/nockpackage.h @@ -1,33 +1,18 @@ #ifndef _PROTOCOL_H #define _PROTOCOL_H -#include "mac.h" +#include -#include - -static const int PORT{2342}; -static const int8_t VERSION{1}; - -class NockPackage +struct NockPackage { -public: - using Hood = std::string; - - NockPackage(); - - NockPackage(const Mac &sourceMac, const Hood &hoodName); - - size_t serialize(uint8_t *buf, size_t maxlen) const; - - bool deserialize(const uint8_t *buf, size_t len); - - Mac getMac() const; - - std::string getHood() const; - -private: - Mac m_sourceMac; - Hood m_hoodName; + uint8_t version; + uint8_t mac[6]; + uint8_t hoodLen; + char hood[]; }; +//size_t NockPackage_serialize(uint8_t *buf, size_t maxlen, const NockPackage *p); + +//uint8_t NockPackage_deserialize(NockPackage *p, const uint8_t *buf, size_t len); + #endif // _PROTOCOL_H diff --git a/tc.c b/tc.c new file mode 100644 index 0000000..c3a8004 --- /dev/null +++ b/tc.c @@ -0,0 +1,88 @@ +#include "tc.h" +#include "log.h" + +#include +#include + +/* + * if=eth0 + * + * # qdisc anlegen: + * tc qdisc add dev $if ingress + * + * # alles sperren: + * tc filter add dev $if protocol all parent ffff: prio 65535 basic match "u32(u16 0x4305 0xffff at -2)" flowid :1 action drop + * + * # eine mac frei schalten: + * tc filter add dev $if protocol all parent ffff: prio 99 basic match "u32(u32 0xf81a67a5 0xffffffff at -8)" and "u32(u16 0xf4cb 0xffff at -4)" flowid :1 action pass + * + * # qdisc anzeigen + * tc qdisc + * + * # qdisc löschen + * tc qdisc del dev $if ingress + * + * # filter anzeigen + * tc filter show dev $if ingress + */ + +extern const char *g_interface; + +void tc_add_qdisc_ingress() +{ + char cmd[2048]; + snprintf(cmd, 2048, "/sbin/tc qdisc add dev %s ingress", g_interface); + log_debug("CMD: %s\n", cmd); + system(cmd); +} + +void tc_del_qdisc_ingress() +{ + char cmd[2048]; + snprintf(cmd, 2048, "/sbin/tc qdisc del dev %s ingress", g_interface); + log_debug("CMD: %s\n", cmd); + system(cmd); +} + +void tc_block_all() +{ + char cmd[2048]; + snprintf(cmd, 2048, "/sbin/tc filter add dev %s protocol all parent ffff: prio 65535 basic match \"u32(u16 0x4305 0xffff at -2)\" flowid :1 action drop", g_interface); + log_debug("CMD: %s\n", cmd); + system(cmd); +} + +void tc_allow_mac(const uint8_t mac[]) +{ + char cmd[2048]; + snprintf(cmd, 2048, "/sbin/tc filter add dev %s protocol all parent ffff: prio 99 " + "basic match \"u32(u32 0x%2x%2x%2x%2x 0xffffffff at -8)\" " + "and \"u32(u16 0x%2x%2x 0xffff at -4)\" flowid :1 action pass", + g_interface, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + log_debug("CMD: %s\n", cmd); + system(cmd); +} + +void tc_disallow_mac(const uint8_t mac[]) +{ + char cmd[2048]; + snprintf(cmd, 2048, "/sbin/tc filter delete dev %s protocol all parent ffff: prio 99 " + "basic match \"u32(u32 0x%2x%2x%2x%2x 0xffffffff at -8)\" " + "and \"u32(u16 0x%2x%2x 0xffff at -4)\" flowid :1 action pass", + g_interface, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + log_debug("CMD: %s\n", cmd); + system(cmd); +} + +void tc_start() +{ + tc_del_qdisc_ingress(); // in case a old session is sill there + + tc_add_qdisc_ingress(); + tc_block_all(); +} + +void tc_stop() +{ + tc_del_qdisc_ingress(); +} diff --git a/tc.cpp b/tc.cpp deleted file mode 100644 index ee02b90..0000000 --- a/tc.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "tc.h" -#include "log.h" - -#include - -/* - * if=eth0 - * - * # qdisc anlegen: - * tc qdisc add dev $if ingress - * - * # alles sperren: - * tc filter add dev $if protocol all parent ffff: prio 65535 basic match "u32(u16 0x4305 0xffff at -2)" flowid :1 action drop - * - * # eine mac frei schalten: - * tc filter add dev $if protocol all parent ffff: prio 99 basic match "u32(u32 0xf81a67a5 0xffffffff at -8)" and "u32(u16 0xf4cb 0xffff at -4)" flowid :1 action pass - * - * # qdisc anzeigen - * tc qdisc - * - * # qdisc löschen - * tc qdisc del dev $if ingress - * - * # filter anzeigen - * tc filter show dev $if ingress - */ - -tc::tc(const std::string &interface) - : m_interface(interface) -{ - del_qdisc_ingress(); // in case a old session is sill there - - add_qdisc_ingress(); - block_all(); -} - -tc::~tc() -{ - del_qdisc_ingress(); -} - -void tc::add_qdisc_ingress() -{ - const std::string cmd{"/sbin/tc qdisc add dev "+m_interface+" ingress"}; - log::debug(std::string("CMD: ") + cmd); - std::system(cmd.c_str()); -} - -void tc::del_qdisc_ingress() -{ - const std::string cmd{"/sbin/tc qdisc del dev "+m_interface+" ingress"}; - log::debug(std::string("CMD: ") + cmd); - std::system(cmd.c_str()); -} - -void tc::block_all() -{ - const std::string cmd{"/sbin/tc filter add dev "+m_interface+" protocol all parent ffff: prio 65535 basic match \"u32(u16 0x4305 0xffff at -2)\" flowid :1 action drop"}; - log::debug(std::string("CMD: ") + cmd); - std::system(cmd.c_str()); -} - -void tc::allow_mac(const std::string &mac) -{ - const std::string cmd{"/sbin/tc filter add dev "+m_interface+" protocol all parent ffff: prio 99 " - "basic match \"u32(u32 0x"+mac.substr(0, 8)+" 0xffffffff at -8)\" " - "and \"u32(u16 0x"+mac.substr(8,10)+" 0xffff at -4)\" flowid :1 action pass"}; - log::debug(std::string("CMD: ") + cmd); - std::system(cmd.c_str()); -} - -void tc::disallow_mac(const std::string &mac) -{ - const std::string cmd{"/sbin/tc filter delete dev "+m_interface+" protocol all parent ffff: prio 99 " - "basic match \"u32(u32 0x"+mac.substr(0, 8)+" 0xffffffff at -8)\" " - "and \"u32(u16 0x"+mac.substr(8,10)+" 0xffff at -4)\" flowid :1 action pass"}; - log::debug(std::string("CMD: ") + cmd); - std::system(cmd.c_str()); -} diff --git a/tc.h b/tc.h index e259961..f6088be 100644 --- a/tc.h +++ b/tc.h @@ -1,30 +1,14 @@ #ifndef _TC_H #define _TC_H -#include +#include -class tc -{ -public: - explicit tc(const std::string &interface); +void tc_start(); - ~tc(); +void tc_stop(); - void add_qdisc_ingress(); +void tc_allow_mac(const uint8_t mac[]); - void del_qdisc_ingress(); - - void block_all(); - - void allow_mac(const std::string &mac); - - void disallow_mac(const std::string &mac); - -private: - tc(const tc&); - tc(); - - const std::string m_interface; -}; +void tc_disallow_mac(const uint8_t mac[]); #endif // _TC_H