Repo-Init
 
Loading...
Searching...
No Matches
RawSocket.cpp
Go to the documentation of this file.
2
4
5#include <chrono>
6#include <cstring>
7#include <ios>
8#include <stdexcept>
9#include <utility>
10
11#include <net/ethernet.h>
12#include <net/if.h>
13#include <netinet/in.h>
14#include <sys/socket.h>
15#include <unistd.h>
16
17void RawSocket::init(int domain, int type, int protocol)
18{
19 _sockFd = socket(domain, type, protocol); // Init socket
20 if (_sockFd < 0)
21 {
22 throw std::ios_base::failure(getErrnoString(errno));
23 }
24 if (bind(_sockFd, reinterpret_cast<sockaddr *>(&_addr), sizeof(_addr)) < 0)
25 {
26 throw std::ios_base::failure(std::string("Bind failed: ") + getErrnoString(errno));
27 }
28}
29
30RawSocket::RawSocket(std::string iface, bool isWrite) : _writeMode(isWrite), _iFace(std::move(iface))
31{
32 // Prepare socket address
33 memset(static_cast<void *>(&_addr), 0, sizeof(sockaddr_ll));
34 _addr.sll_family = AF_PACKET;
35 _addr.sll_protocol = htons(ETH_P_ALL);
36 _addr.sll_ifindex = static_cast<int>(if_nametoindex(_iFace.c_str()));
37 if (_addr.sll_ifindex == 0)
38 {
39 throw std::ios_base::failure(std::string("Can't find interface: ") + getErrnoString(errno));
40 }
41
42 // Interface request
43 ifreq ifr{};
44 memset(static_cast<void *>(&ifr), 0, sizeof(ifreq));
45 memcpy(std::addressof(ifr.ifr_name), _iFace.c_str(),
46 _iFace.size()); // Size should be sufficient because if_nametoindex not failed
47
48 if (isWrite)
49 {
50 init(PF_PACKET, SOCK_RAW, IPPROTO_RAW);
51 if (setsockopt(_sockFd, SOL_SOCKET, SO_BINDTODEVICE, static_cast<void *>(&ifr), sizeof(ifr)) < 0)
52 {
53 throw std::ios_base::failure(std::string("Can't set socket options: ") + getErrnoString(errno));
54 }
55 }
56 else
57 {
58 init(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
59 }
60 _isReady = true;
61}
62
63int RawSocket::writeData(const unsigned char *data, size_t dataLen)
64{
65 if (!_isReady || !_writeMode)
66 {
67 return -EPERM;
68 }
69
70 auto startTime = std::chrono::high_resolution_clock::now();
71 const auto retval = static_cast<int>(write(_sockFd, data, dataLen));
72
73 // Update stats
74 _stats.processingTime += static_cast<double>((std::chrono::high_resolution_clock::now() - startTime).count());
75 _stats.sentBytes += dataLen;
76
77 return retval;
78}
79
80int RawSocket::readData(unsigned char *data, size_t dataLen)
81{
82 if (!_isReady || _writeMode)
83 {
84 return -EPERM;
85 }
86 // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
87 socklen_t socketLen = sizeof(_addr);
88
89 auto startTime = std::chrono::high_resolution_clock::now();
90 const auto retval =
91 static_cast<int>(recvfrom(_sockFd, data, dataLen, 0, reinterpret_cast<sockaddr *>(&_addr), &socketLen));
92
93 // Update stats
94 _stats.processingTime += static_cast<double>((std::chrono::high_resolution_clock::now() - startTime).count());
95 _stats.receivedBytes += dataLen;
96
97 return retval;
98}
99
100RawSocketStats RawSocket::getStats(bool resetInternalStats)
101{
102 if (resetInternalStats)
103 {
104 RawSocketStats buffer = _stats;
105 _stats = {0, 0, 0.0};
106 return buffer;
107 }
108 return _stats;
109}
110
std::string getErrnoString(int errVal)
int _sockFd
Socket descriptor.
Definition RawSocket.hpp:30
RawSocket(std::string iface, bool isWrite=false)
Definition RawSocket.cpp:30
bool _writeMode
Mode indicator. True = Write, False = Read.
Definition RawSocket.hpp:28
RawSocketStats _stats
Internal structure for statistics.
Definition RawSocket.hpp:36
RawSocketStats getStats(bool resetInternalStats=false)
bool _isReady
Ready flag.
Definition RawSocket.hpp:26
void init(int domain, int type, int protocol)
Definition RawSocket.cpp:17
std::string _iFace
Currently used ethernet interface.
Definition RawSocket.hpp:32
int readData(unsigned char *data, size_t dataLen)
Definition RawSocket.cpp:80
int writeData(const unsigned char *data, size_t dataLen)
Definition RawSocket.cpp:63
sockaddr_ll _addr
Socket structure.
Definition RawSocket.hpp:34
size_t receivedBytes
Number of bytes read from socket.
Definition RawSocket.hpp:14
size_t sentBytes
Number of bytes written to socket.
Definition RawSocket.hpp:12
double processingTime
Total execution time in nanoseconds.
Definition RawSocket.hpp:16