macnocker/macnockclient.cpp

108 lines
2.8 KiB
C++

#include "macnockclient.h"
#include "nockpackage.h"
#include "log.h"
#include <vector>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <thread>
#include <chrono>
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<uint8_t>(ifr.ifr_hwaddr.sa_data[0]), static_cast<uint8_t>(ifr.ifr_hwaddr.sa_data[1]),
static_cast<uint8_t>(ifr.ifr_hwaddr.sa_data[2]), static_cast<uint8_t>(ifr.ifr_hwaddr.sa_data[3]),
static_cast<uint8_t>(ifr.ifr_hwaddr.sa_data[4]), static_cast<uint8_t>(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<sockaddr *>(&servaddr), sizeof(servaddr));
if (sent == -1)
{
log::error(std::string("[c] ERROR: Can't send data (") + strerror(errno) + ").");
}
else if (static_cast<size_t>(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;
}