INET Framework for OMNeT++/OMNEST
inet::PcapRecorder Class Reference

Dumps every packet using the IPacketWriter and PacketDump classes. More...

#include <PcapRecorder.h>

Inheritance diagram for inet::PcapRecorder:
inet::StringFormat::IDirectiveResolver

Classes

class  IHelper
 

Public Member Functions

 PcapRecorder ()
 
virtual ~PcapRecorder ()
 
virtual const char * resolveDirective (char directive) const override
 

Protected Types

typedef std::map< simsignal_t, DirectionSignalList
 

Protected Member Functions

virtual void initialize () override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void refreshDisplay () const override
 
virtual void updateDisplayString () const
 
virtual void finish () override
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
virtual void recordPacket (const cPacket *msg, Direction direction, cComponent *source)
 
virtual bool matchesLinkType (PcapLinkType pcapLinkType, const Protocol *protocol) const
 
virtual PackettryConvertToLinkType (const Packet *packet, PcapLinkType pcapLinkType, const Protocol *protocol) const
 
virtual PcapLinkType protocolToLinkType (const Protocol *protocol) const
 

Protected Attributes

std::vector< const Protocol * > dumpProtocols
 
SignalList signalList
 
IPcapWriterpcapWriter = nullptr
 
unsigned int snaplen = 0
 
bool dumpBadFrames = false
 
PacketFilter packetFilter
 
int numRecorded = 0
 
bool verbose = false
 
bool recordPcap = false
 
std::vector< IHelper * > helpers
 
PacketPrinter packetPrinter
 

Static Protected Attributes

static simsignal_t packetRecordedSignal = registerSignal("packetRecorded")
 

Detailed Description

Dumps every packet using the IPacketWriter and PacketDump classes.

Member Typedef Documentation

◆ SignalList

typedef std::map<simsignal_t, Direction> inet::PcapRecorder::SignalList
protected

Constructor & Destructor Documentation

◆ PcapRecorder()

inet::PcapRecorder::PcapRecorder ( )
38  : cSimpleModule()
39 {
40 }

◆ ~PcapRecorder()

inet::PcapRecorder::~PcapRecorder ( )
virtual
32 {
33  delete pcapWriter;
34  for (auto helper : helpers)
35  delete helper;
36 }

Member Function Documentation

◆ finish()

void inet::PcapRecorder::finish ( )
overrideprotectedvirtual
237 {
238  pcapWriter->close();
239 }

◆ handleMessage()

void inet::PcapRecorder::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
132 {
133  throw cRuntimeError("This module does not handle messages");
134 }

◆ initialize()

void inet::PcapRecorder::initialize ( )
overrideprotectedvirtual
43 {
44  verbose = par("verbose");
45  snaplen = this->par("snaplen");
46  dumpBadFrames = par("dumpBadFrames");
47  signalList.clear();
48  packetFilter.setExpression(par("packetFilter").objectValue());
49 
50  {
51  cStringTokenizer signalTokenizer(par("sendingSignalNames"));
52 
53  while (signalTokenizer.hasMoreTokens())
54  signalList[registerSignal(signalTokenizer.nextToken())] = DIRECTION_OUTBOUND;
55  }
56 
57  {
58  cStringTokenizer signalTokenizer(par("receivingSignalNames"));
59 
60  while (signalTokenizer.hasMoreTokens())
61  signalList[registerSignal(signalTokenizer.nextToken())] = DIRECTION_INBOUND;
62  }
63 
64  {
65  cStringTokenizer protocolTokenizer(par("dumpProtocols"));
66 
67  while (protocolTokenizer.hasMoreTokens())
68  dumpProtocols.push_back(Protocol::getProtocol(protocolTokenizer.nextToken()));
69  }
70 
71  {
72  cStringTokenizer protocolTokenizer(par("helpers"));
73 
74  while (protocolTokenizer.hasMoreTokens())
75  helpers.push_back(check_and_cast<IHelper *>(createOne(protocolTokenizer.nextToken())));
76  }
77 
78  const char *moduleNames = par("moduleNamePatterns");
79  cStringTokenizer moduleTokenizer(moduleNames);
80 
81  while (moduleTokenizer.hasMoreTokens()) {
82  bool found = false;
83  std::string mname(moduleTokenizer.nextToken());
84  bool isAllIndex = (mname.length() > 3) && mname.rfind("[*]") == mname.length() - 3;
85 
86  if (isAllIndex)
87  mname.replace(mname.length() - 3, 3, "");
88 
89  if (mname[0] == '.') {
90  for (auto& elem : signalList)
91  getParentModule()->subscribe(elem.first, this);
92  found = true;
93  }
94  else {
95  for (cModule::SubmoduleIterator i(getParentModule()); !i.end(); i++) {
96  cModule *submod = *i;
97  if (0 == strcmp(isAllIndex ? submod->getName() : submod->getFullName(), mname.c_str())) {
98  found = true;
99 
100  for (auto& elem : signalList) {
101  if (!submod->isSubscribed(elem.first, this)) {
102  submod->subscribe(elem.first, this);
103  EV_INFO << "Subscribing to " << submod->getFullPath() << ":" << getSignalName(elem.first) << EV_ENDL;
104  }
105  }
106  }
107  }
108  }
109 
110  if (!found && !isAllIndex)
111  EV_INFO << "The module " << mname << (isAllIndex ? "[*]" : "") << " not found" << EV_ENDL;
112  }
113 
114  const char *file = par("pcapFile");
115  const char *fileFormat = par("fileFormat");
116  if (!strcmp(fileFormat, "pcap"))
117  pcapWriter = new PcapWriter();
118  else if (!strcmp(fileFormat, "pcapng"))
119  pcapWriter = new PcapngWriter();
120  else
121  throw cRuntimeError("Unknown fileFormat parameter");
122  recordPcap = *file != '\0';
123  if (recordPcap) {
124  pcapWriter->open(file, snaplen);
125  pcapWriter->setFlush(par("alwaysFlush"));
126  }
127 
128  WATCH(numRecorded);
129 }

◆ matchesLinkType()

bool inet::PcapRecorder::matchesLinkType ( PcapLinkType  pcapLinkType,
const Protocol protocol 
) const
protectedvirtual
242 {
243  if (protocol == nullptr)
244  return false;
245  else if (*protocol == Protocol::ethernetPhy)
246  return pcapLinkType == LINKTYPE_ETHERNET_MPACKET;
247  else if (*protocol == Protocol::ethernetMac)
248  return pcapLinkType == LINKTYPE_ETHERNET;
249  else if (*protocol == Protocol::ppp)
250  return pcapLinkType == LINKTYPE_PPP_WITH_DIR;
251  else if (*protocol == Protocol::ieee80211Mac)
252  return pcapLinkType == LINKTYPE_IEEE802_11;
253  else if (*protocol == Protocol::ipv4)
254  return pcapLinkType == LINKTYPE_RAW || pcapLinkType == LINKTYPE_IPV4;
255  else if (*protocol == Protocol::ipv6)
256  return pcapLinkType == LINKTYPE_RAW || pcapLinkType == LINKTYPE_IPV6;
257  else if (*protocol == Protocol::ieee802154)
258  return pcapLinkType == LINKTYPE_IEEE802_15_4 || pcapLinkType == LINKTYPE_IEEE802_15_4_NOFCS;
259  else {
260  for (auto helper : helpers) {
261  if (helper->matchesLinkType(pcapLinkType, protocol))
262  return true;
263  }
264  }
265  return false;
266 }

Referenced by recordPacket().

◆ protocolToLinkType()

PcapLinkType inet::PcapRecorder::protocolToLinkType ( const Protocol protocol) const
protectedvirtual
269 {
272  else if (*protocol == Protocol::ethernetMac)
273  return LINKTYPE_ETHERNET;
274  else if (*protocol == Protocol::ppp)
275  return LINKTYPE_PPP_WITH_DIR;
276  else if (*protocol == Protocol::ieee80211Mac)
277  return LINKTYPE_IEEE802_11;
278  else if (*protocol == Protocol::ipv4 || *protocol == Protocol::ipv6)
279  return LINKTYPE_RAW;
280  else if (*protocol == Protocol::ieee802154)
281  return LINKTYPE_IEEE802_15_4;
282  else {
283  for (auto helper : helpers) {
284  auto lt = helper->protocolToLinkType(protocol);
285  if (lt != LINKTYPE_INVALID)
286  return lt;
287  }
288  }
289  return LINKTYPE_INVALID;
290 }

Referenced by recordPacket().

◆ receiveSignal()

void inet::PcapRecorder::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual
163 {
164  Enter_Method("%s", cComponent::getSignalName(signalID));
165 
166  if (pcapWriter->isOpen()) {
167  cPacket *packet = dynamic_cast<cPacket *>(obj);
168 
169  if (packet) {
170  auto i = signalList.find(signalID);
171  Direction direction = (i != signalList.end()) ? i->second : DIRECTION_UNDEFINED;
172  recordPacket(packet, direction, source);
173  }
174  }
175 }

◆ recordPacket()

void inet::PcapRecorder::recordPacket ( const cPacket *  msg,
Direction  direction,
cComponent *  source 
)
protectedvirtual
178 {
179  if (auto packet = dynamic_cast<const Packet *>(cpacket)) {
180  EV_INFO << "Recording packet" << EV_FIELD(source, source->getFullPath()) << EV_FIELD(direction, direction) << EV_FIELD(packet) << EV_ENDL;
181  if (verbose)
182  EV_DEBUG << "Dumping packet" << EV_FIELD(packet, packetPrinter.printPacketToString(const_cast<Packet *>(packet), "%i")) << EV_ENDL;
183  if (recordPcap && packetFilter.matches(packet) && (dumpBadFrames || !packet->hasBitError())) {
184  // get Direction
185  if (direction == DIRECTION_UNDEFINED) {
186  if (auto directionTag = packet->findTag<DirectionTag>())
187  direction = directionTag->getDirection();
188  }
189 
190  // get NetworkInterface
191  auto srcModule = check_and_cast<cModule *>(source);
192  auto networkInterface = findContainingNicModule(srcModule);
193  if (networkInterface == nullptr) {
194  int ifaceId = -1;
195  if (direction == DIRECTION_OUTBOUND) {
196  if (auto ifaceTag = packet->findTag<InterfaceReq>())
197  ifaceId = ifaceTag->getInterfaceId();
198  }
199  else if (direction == DIRECTION_INBOUND) {
200  if (auto ifaceTag = packet->findTag<InterfaceInd>())
201  ifaceId = ifaceTag->getInterfaceId();
202  }
203  if (ifaceId != -1) {
204  auto ift = check_and_cast_nullable<InterfaceTable *>(getContainingNode(srcModule)->getSubmodule("interfaceTable"));
205  networkInterface = ift->getInterfaceById(ifaceId);
206  }
207  }
208 
209  const auto& packetProtocolTag = packet->getTag<PacketProtocolTag>();
210  auto protocol = packetProtocolTag->getProtocol();
211  if (packetProtocolTag->getFrontOffset() == b(0) && packetProtocolTag->getBackOffset() == b(0) && contains(dumpProtocols, protocol)) {
212  auto pcapLinkType = protocolToLinkType(protocol);
213  if (pcapLinkType == LINKTYPE_INVALID)
214  throw cRuntimeError("Cannot determine the PCAP link type from protocol '%s'", protocol->getName());
215 
216  if (matchesLinkType(pcapLinkType, protocol)) {
217  pcapWriter->writePacket(simTime(), packet, direction, networkInterface, pcapLinkType);
218  numRecorded++;
219  emit(packetRecordedSignal, packet);
220  }
221  else {
222  if (auto convertedPacket = tryConvertToLinkType(packet, pcapLinkType, protocol)) {
223  pcapWriter->writePacket(simTime(), convertedPacket, direction, networkInterface, pcapLinkType);
224  numRecorded++;
225  emit(packetRecordedSignal, packet);
226  delete convertedPacket;
227  }
228  else
229  throw cRuntimeError("The protocol '%s' doesn't match PCAP link type %d", protocol->getName(), pcapLinkType);
230  }
231  }
232  }
233  }
234 }

Referenced by receiveSignal().

◆ refreshDisplay()

void inet::PcapRecorder::refreshDisplay ( ) const
overrideprotectedvirtual
137 {
139 }

◆ resolveDirective()

const char * inet::PcapRecorder::resolveDirective ( char  directive) const
overridevirtual

Implements inet::StringFormat::IDirectiveResolver.

142 {
143  static std::string result;
144  switch (directive) {
145  case 'n':
146  result = std::to_string(numRecorded);
147  break;
148  default:
149  throw cRuntimeError("Unknown directive: %c", directive);
150  }
151  return result.c_str();
152 }

◆ tryConvertToLinkType()

Packet * inet::PcapRecorder::tryConvertToLinkType ( const Packet packet,
PcapLinkType  pcapLinkType,
const Protocol protocol 
) const
protectedvirtual
293 {
294  for (IHelper *helper : helpers) {
295  if (auto newPacket = helper->tryConvertToLinkType(packet, pcapLinkType, protocol))
296  return newPacket;
297  }
298  return nullptr;
299 }

Referenced by recordPacket().

◆ updateDisplayString()

void inet::PcapRecorder::updateDisplayString ( ) const
protectedvirtual
155 {
156  if (getEnvir()->isGUI()) {
157  auto text = StringFormat::formatString(par("displayStringTextFormat"), this);
158  getDisplayString().setTagArg("t", 0, text);
159  }
160 }

Referenced by refreshDisplay().

Member Data Documentation

◆ dumpBadFrames

bool inet::PcapRecorder::dumpBadFrames = false
protected

Referenced by initialize(), and recordPacket().

◆ dumpProtocols

std::vector<const Protocol *> inet::PcapRecorder::dumpProtocols
protected

Referenced by initialize(), and recordPacket().

◆ helpers

std::vector<IHelper *> inet::PcapRecorder::helpers
protected

◆ numRecorded

int inet::PcapRecorder::numRecorded = 0
protected

◆ packetFilter

PacketFilter inet::PcapRecorder::packetFilter
protected

Referenced by initialize(), and recordPacket().

◆ packetPrinter

PacketPrinter inet::PcapRecorder::packetPrinter
protected

Referenced by recordPacket().

◆ packetRecordedSignal

simsignal_t inet::PcapRecorder::packetRecordedSignal = registerSignal("packetRecorded")
staticprotected

Referenced by recordPacket().

◆ pcapWriter

IPcapWriter* inet::PcapRecorder::pcapWriter = nullptr
protected

◆ recordPcap

bool inet::PcapRecorder::recordPcap = false
protected

Referenced by initialize(), and recordPacket().

◆ signalList

SignalList inet::PcapRecorder::signalList
protected

Referenced by initialize(), and receiveSignal().

◆ snaplen

unsigned int inet::PcapRecorder::snaplen = 0
protected

Referenced by initialize().

◆ verbose

bool inet::PcapRecorder::verbose = false
protected

Referenced by initialize(), and recordPacket().


The documentation for this class was generated from the following files:
inet::DIRECTION_INBOUND
@ DIRECTION_INBOUND
Definition: DirectionTag_m.h:57
inet::PcapRecorder::tryConvertToLinkType
virtual Packet * tryConvertToLinkType(const Packet *packet, PcapLinkType pcapLinkType, const Protocol *protocol) const
Definition: PcapRecorder.cc:292
inet::DIRECTION_OUTBOUND
@ DIRECTION_OUTBOUND
Definition: DirectionTag_m.h:58
inet::PcapRecorder::updateDisplayString
virtual void updateDisplayString() const
Definition: PcapRecorder.cc:154
inet::LINKTYPE_ETHERNET_MPACKET
@ LINKTYPE_ETHERNET_MPACKET
mPackets, as specified by IEEE 802.3br Figure 99-4, starting with the preamble and always ending with...
Definition: IPcapWriter.h:200
protocol
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down protocol
Definition: IUdp-gates.txt:25
inet::findContainingNicModule
NetworkInterface * findContainingNicModule(const cModule *from)
Find the nic module (inside the networkNode) containing the given module.
Definition: NetworkInterface.cc:679
inet::PacketFilter::setExpression
void setExpression(const char *expression)
Definition: common/packet/PacketFilter.cc:39
inet::IPcapWriter::writePacket
virtual void writePacket(simtime_t time, const Packet *packet, Direction direction, NetworkInterface *ie, PcapLinkType linkType)=0
inet::Protocol::ipv4
static const Protocol ipv4
Definition: Protocol.h:93
inet::Protocol::getProtocol
static const Protocol * getProtocol(int id)
Definition: Protocol.cc:50
inet::Protocol::ipv6
static const Protocol ipv6
Definition: Protocol.h:94
inet::LINKTYPE_IEEE802_11
@ LINKTYPE_IEEE802_11
IEEE 802.11 wireless LAN.
Definition: IPcapWriter.h:50
inet::PcapRecorder::pcapWriter
IPcapWriter * pcapWriter
Definition: PcapRecorder.h:43
inet::getContainingNode
cModule * getContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:40
InterfaceReq
removed InterfaceReq
Definition: IUdp-gates.txt:11
inet::IPcapWriter::isOpen
virtual bool isOpen() const =0
inet::LINKTYPE_IEEE802_15_4_NOFCS
@ LINKTYPE_IEEE802_15_4_NOFCS
IEEE 802.15.4 wireless Personal Area Network, without the FCS at the end of the frame.
Definition: IPcapWriter.h:142
inet::LINKTYPE_INVALID
@ LINKTYPE_INVALID
Definition: IPcapWriter.h:18
inet::IPcapWriter::close
virtual void close()=0
inet::LINKTYPE_RAW
@ LINKTYPE_RAW
Raw IP.
Definition: IPcapWriter.h:46
inet::PcapRecorder::recordPcap
bool recordPcap
Definition: PcapRecorder.h:49
inet::utils::createOne
cObject * createOne(const char *className, const char *defaultNamespace)
Like cObjectFactory::createOne(), except it starts searching for the class in the given namespace.
Definition: INETUtils.cc:147
inet::LINKTYPE_IPV6
@ LINKTYPE_IPV6
Raw IPv6; the packet begins with an IPv6 header.
Definition: IPcapWriter.h:140
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::PcapRecorder::dumpBadFrames
bool dumpBadFrames
Definition: PcapRecorder.h:45
inet::Protocol::ppp
static const Protocol ppp
Definition: Protocol.h:104
inet::Protocol::ieee802154
static const Protocol ieee802154
Definition: Protocol.h:83
inet::PacketFilter::matches
bool matches(const cPacket *packet) const
Definition: common/packet/PacketFilter.cc:92
inet::PcapRecorder::dumpProtocols
std::vector< const Protocol * > dumpProtocols
Definition: PcapRecorder.h:41
inet::PcapRecorder::packetFilter
PacketFilter packetFilter
Definition: PcapRecorder.h:46
EV_FIELD
#define EV_FIELD(...)
Definition: INETDefs.h:112
inet::LINKTYPE_PPP_WITH_DIR
@ LINKTYPE_PPP_WITH_DIR
PPP, as per RFC 1661 and RFC 1662, preceded with a one-byte pseudo-header with a zero value meaning "...
Definition: IPcapWriter.h:118
inet::PcapRecorder::verbose
bool verbose
Definition: PcapRecorder.h:48
inet::contains
bool contains(const std::vector< T > &v, const Tk &a)
Definition: stlutils.h:65
inet::IPcapWriter::open
virtual void open(const char *filename, unsigned int snaplen)=0
inet::PcapRecorder::signalList
SignalList signalList
Definition: PcapRecorder.h:42
inet::Direction
Direction
Enum generated from inet/common/DirectionTag.msg:13 by opp_msgtool.
Definition: DirectionTag_m.h:55
inet::Protocol::ethernetMac
static const Protocol ethernetMac
Definition: Protocol.h:65
inet::PacketPrinter::printPacketToString
virtual std::string printPacketToString(Packet *packet, const char *format=nullptr) const
Definition: PacketPrinter.cc:223
inet::PcapRecorder::packetPrinter
PacketPrinter packetPrinter
Definition: PcapRecorder.h:51
inet::PcapRecorder::numRecorded
int numRecorded
Definition: PcapRecorder.h:47
inet::PcapRecorder::matchesLinkType
virtual bool matchesLinkType(PcapLinkType pcapLinkType, const Protocol *protocol) const
Definition: PcapRecorder.cc:241
inet::PcapRecorder::helpers
std::vector< IHelper * > helpers
Definition: PcapRecorder.h:50
inet::units::values::b
value< int64_t, units::b > b
Definition: Units.h:1241
inet::DIRECTION_UNDEFINED
@ DIRECTION_UNDEFINED
Definition: DirectionTag_m.h:56
inet::IPcapWriter::setFlush
virtual void setFlush(bool flush)=0
inet::Protocol::ethernetPhy
static const Protocol ethernetPhy
Definition: Protocol.h:66
inet::StringFormat::formatString
const char * formatString(IDirectiveResolver *resolver) const
Definition: StringFormat.cc:17
Enter_Method
#define Enter_Method(...)
Definition: SelfDoc.h:71
inet::PcapRecorder::protocolToLinkType
virtual PcapLinkType protocolToLinkType(const Protocol *protocol) const
Definition: PcapRecorder.cc:268
inet::Protocol::ieee80211Mac
static const Protocol ieee80211Mac
Definition: Protocol.h:79
inet::LINKTYPE_IPV4
@ LINKTYPE_IPV4
Raw IPv4; the packet begins with an IPv4 header.
Definition: IPcapWriter.h:138
inet::PcapRecorder::recordPacket
virtual void recordPacket(const cPacket *msg, Direction direction, cComponent *source)
Definition: PcapRecorder.cc:177
inet::LINKTYPE_ETHERNET
@ LINKTYPE_ETHERNET
IEEE 802.3 Ethernet.
Definition: IPcapWriter.h:22
EV_ENDL
#define EV_ENDL
Definition: INETDefs.h:114
inet::PcapRecorder::packetRecordedSignal
static simsignal_t packetRecordedSignal
Definition: PcapRecorder.h:53
inet::PcapRecorder::snaplen
unsigned int snaplen
Definition: PcapRecorder.h:44
inet::LINKTYPE_IEEE802_15_4
@ LINKTYPE_IEEE802_15_4
IEEE 802.15.4 wireless Personal Area Network.
Definition: IPcapWriter.h:106