pcapBackend.cpp
Go to the documentation of this file.
1 #ifdef WITH_PCAP
2 
3 #include "pcapBackend.hpp"
4 #include "common.hpp"
5 
6 #include <sys/types.h>
7 #include <unistd.h>
8 
9 using namespace std;
10 
11 PcapBackend::PcapBackend(
12  string dev, array<uint8_t, 6> srcMac //,
13  // StateMachine<TupleIdent, SamplePacket> &sm
14  )
15  : dev(dev), /* sm(sm), */ srcMac(srcMac) {
16 
17  if (geteuid() != 0) {
18  cout << "WARNING: Running pcap wihout root priviledges may be a bad idea" << endl;
19  }
20 
21  handle = pcap_open_live(dev.c_str(), bufSize, 1, 1, errbuf);
22  if (handle == NULL) {
23  cout << "PcapBackend: pcap_open_live() failed" << endl;
24  abort();
25  }
26 
27  if (pcap_setnonblock(handle, 1, errbuf) < 0) {
28  cout << "PcapBackend: pcap_setnonblock() failed" << endl;
29  abort();
30  }
31 
32  D(cout << "PcapBackend: device opened" << endl;)
33 };
34 
35 PcapBackend::~PcapBackend() {
36  pcap_close(handle);
37  for (auto i : packetPool) {
38  delete (i);
39  }
40 };
41 
42 void PcapBackend::sendBatch(BufArray<SamplePacket> &pkts) {
43  auto sendCount = pkts.getSendCount();
44  SamplePacket **spArray = reinterpret_cast<SamplePacket **>(malloc(sizeof(void *) * 64));
45  pkts.getSendBufs(spArray);
46 
47  for (uint32_t i = 0; i < sendCount; i++) {
48  SamplePacket *p = spArray[i];
49 
50  // Set some valid ethernet header
51  struct ether_header *eth = reinterpret_cast<ether_header *>(p->getData());
52  memset(eth->ether_dhost, 0xff, 6);
53  memcpy(eth->ether_shost, srcMac.data(), 6);
54  eth->ether_type = htons(ETHERTYPE_IP);
55 
56  // Actually inject packet
57  if (pcap_inject(handle, p->getData(), p->getDataLen()) != (int)p->getDataLen()) {
58  cout << "PcapBackend::sendBatch() pcap_inject() failed" << endl;
59  abort();
60  }
61 
62  // Give buffer back to the pool
63  packetPool.push_back(p);
64  }
65 
66  free(spArray);
67 };
68 
69 void PcapBackend::freeBatch(BufArray<SamplePacket> &pkts) {
70  auto freeCount = pkts.getFreeCount();
71  SamplePacket **spArray = reinterpret_cast<SamplePacket **>(malloc(sizeof(void *) * 64));
72  pkts.getFreeBufs(spArray);
73 
74  for (uint32_t i = 0; i < freeCount; i++) {
75  packetPool.push_back(spArray[i]);
76  }
77 
78  free(spArray);
79 };
80 
81 BufArray<SamplePacket> *PcapBackend::recvBatch() {
82 
83  // Prepare the packet array
84  SamplePacket **spArray = reinterpret_cast<SamplePacket **>(malloc(sizeof(void *) * 64));
85 
86  struct pcap_pkthdr header;
87  const u_char *pcapPacket;
88 
89  unsigned int count = 0;
90 
91  while ((pcapPacket = pcap_next(handle, &header)) && count < 64) {
92  // If a packet is larger than bufSize, I don't want it anyways...
93  if (header.len > bufSize) {
94  continue;
95  }
96  SamplePacket *pkt = getPkt();
97  memcpy(pkt->getData(), pcapPacket, header.len);
98  pkt->setDataLen(header.len);
99  count++;
100  D(cout << "PcapBackend::recvBatch() got another packet" << endl;)
101  }
102 
103  // Prepare one BufArray
104  BufArray<SamplePacket> *pkts = new BufArray<SamplePacket>(spArray, count);
105 
106  return pkts;
107 };
108 
109 SamplePacket *PcapBackend::getPkt() {
110  if (packetPool.empty()) {
111  void *data = malloc(bufSize);
112  return new SamplePacket(data, 0);
113  } else {
114  SamplePacket *sp = packetPool.back();
115  packetPool.pop_back();
116  sp->setDataLen(0);
117  return sp;
118  }
119 };
120 
121 #endif /* WITH_PCAP */
void * getData()
void setDataLen(uint16_t l)
uint32_t getFreeCount() const
Get the number of packets currently marked as free.
Definition: bufArray.hpp:166
#define D(x)
Definition: common.hpp:10
Example for a packet class.
uint16_t getDataLen()
uint32_t getSendCount() const
Get the number of packets currently marked as send.
Definition: bufArray.hpp:151
void getSendBufs(Packet **sendBufs) const
Get all the packets which are to be sent.
Definition: bufArray.hpp:175
void getFreeBufs(Packet **freeBufs) const
Get all the packets which are to be freed.
Definition: bufArray.hpp:193
Wrapper around MoonGen bufarrays.
Definition: bufArray.hpp:42