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

Dumps packets into a PCAP Next Generation file; see the "pcap-savefile" man page or http://www.tcpdump.org/ for details on the file format. More...

#include <PcapngWriter.h>

Inheritance diagram for inet::PcapngWriter:
inet::IPcapWriter

Public Member Functions

 PcapngWriter ()
 Constructor. More...
 
 ~PcapngWriter ()
 Destructor. More...
 
void open (const char *filename, unsigned int snaplen) override
 Opens a PCAP file with the given file name. More...
 
bool isOpen () const override
 Returns true if the pcap file is currently open. More...
 
void writeInterface (NetworkInterface *networkInterface, PcapLinkType linkType)
 Records the interface into the output file. More...
 
void writePacket (simtime_t time, const Packet *packet, Direction direction, NetworkInterface *ie, PcapLinkType linkType) override
 Records the given packet into the output file if it is open, and throws an exception otherwise. More...
 
void close () override
 Closes the output file if it is open. More...
 
void setFlush (bool flush) override
 Force flushing of pcap dump. More...
 
- Public Member Functions inherited from inet::IPcapWriter
virtual ~IPcapWriter ()
 

Protected Attributes

std::string fileName
 
FILE * dumpfile = nullptr
 
bool flush = false
 
int nextPcapngInterfaceId = 0
 
std::map< int, int > interfaceModuleIdToPcapngInterfaceId
 

Detailed Description

Dumps packets into a PCAP Next Generation file; see the "pcap-savefile" man page or http://www.tcpdump.org/ for details on the file format.

Constructor & Destructor Documentation

◆ PcapngWriter()

inet::PcapngWriter::PcapngWriter ( )
inline

Constructor.

It does not open the output file.

34 {}

◆ ~PcapngWriter()

inet::PcapngWriter::~PcapngWriter ( )

Destructor.

It closes the output file if it is open.

82 {
83  PcapngWriter::close(); // NOTE: admitting that this will not call overridden methods from the destructor
84 }

Member Function Documentation

◆ close()

void inet::PcapngWriter::close ( )
overridevirtual

Closes the output file if it is open.

Implements inet::IPcapWriter.

262 {
263  if (dumpfile) {
264  fclose(dumpfile);
265  dumpfile = nullptr;
266  }
267 }

Referenced by ~PcapngWriter().

◆ isOpen()

bool inet::PcapngWriter::isOpen ( ) const
inlineoverridevirtual

Returns true if the pcap file is currently open.

Implements inet::IPcapWriter.

50 { return dumpfile != nullptr; }

◆ open()

void inet::PcapngWriter::open ( const char *  filename,
unsigned int  snaplen 
)
overridevirtual

Opens a PCAP file with the given file name.

Throws an exception if the file cannot be opened.

Implements inet::IPcapWriter.

87 {
88  if (opp_isempty(filename))
89  throw cRuntimeError("Cannot open pcap file: file name is empty");
90 
92  dumpfile = fopen(filename, "wb");
93  fileName = filename;
94 
95  if (!dumpfile)
96  throw cRuntimeError("Cannot open pcap file [%s] for writing: %s", filename, strerror(errno));
97 
98  flush = false;
99 
100  // header
101  int blockTotalLength = 28;
102  ASSERT(blockTotalLength % 4 == 0);
103  struct pcapng_section_block_header sbh;
104  sbh.blockTotalLength = blockTotalLength;
105  sbh.byteOrderMagic = PCAP_MAGIC;
106  sbh.majorVersion = 1;
107  sbh.minorVersion = 0;
108  sbh.sectionLength = -1L;
109  fwrite(&sbh, sizeof(sbh), 1, dumpfile);
110 
111  // trailer
112  struct pcapng_section_block_trailer sbt;
113  sbt.blockTotalLength = blockTotalLength;
114  fwrite(&sbt, sizeof(sbt), 1, dumpfile);
115 }

◆ setFlush()

void inet::PcapngWriter::setFlush ( bool  flush)
inlineoverridevirtual

Force flushing of pcap dump.

Implements inet::IPcapWriter.

71 { this->flush = flush; }

◆ writeInterface()

void inet::PcapngWriter::writeInterface ( NetworkInterface networkInterface,
PcapLinkType  linkType 
)

Records the interface into the output file.

118 {
119  EV_INFO << "Writing interface to file" << EV_FIELD(fileName) << EV_FIELD(networkInterface) << EV_ENDL;
120  if (!dumpfile)
121  throw cRuntimeError("Cannot write interface: pcap output file is not open");
122 
123  std::string name = networkInterface->getInterfaceName();
124  std::string fullPath = networkInterface->getInterfaceFullPath();
125  fullPath = fullPath.substr(fullPath.find('.') + 1);
126  uint32_t optionsLength = (4 + roundUp(name.length())) + (4 + roundUp(fullPath.length())) + (4 + 8) + (4 + 4 + 4) + 4;
127  uint32_t blockTotalLength = 20 + optionsLength;
128  ASSERT(blockTotalLength % 4 == 0);
129 
130  // header
131  pcapng_interface_block_header ibh;
132  ibh.blockTotalLength = blockTotalLength;
133  ibh.linkType = linkType;
134  ibh.reserved = 0;
135  ibh.snaplen = 0;
136  fwrite(&ibh, sizeof(ibh), 1, dumpfile);
137 
138  // interface name option
139  pcapng_option_header doh;
140  doh.code = 0x0002;
141  doh.length = name.length();
142  fwrite(&doh, sizeof(doh), 1, dumpfile);
143  fwrite(name.c_str(), name.length(), 1, dumpfile);
144  char padding[] = { 0, 0, 0, 0 };
145  int paddingLength = pad(name.length());
146  fwrite(padding, paddingLength, 1, dumpfile);
147 
148  // interface description option
149  doh.code = 0x0003;
150  doh.length = fullPath.length();
151  fwrite(&doh, sizeof(doh), 1, dumpfile);
152  fwrite(fullPath.c_str(), fullPath.length(), 1, dumpfile);
153  paddingLength = pad(fullPath.length());
154  fwrite(padding, paddingLength, 1, dumpfile);
155 
156  // MAC address option
157  doh.code = 0x0006;
158  doh.length = 6;
159  fwrite(&doh, sizeof(doh), 1, dumpfile);
160  uint8_t macAddressBytes[6];
161  networkInterface->getMacAddress().getAddressBytes(macAddressBytes);
162  fwrite(macAddressBytes, 6, 1, dumpfile);
163  fwrite(padding, 2, 1, dumpfile);
164 
165  // IP address/netmask option
166  doh.code = 0x0004;
167  doh.length = 4 + 4;
168  fwrite(&doh, sizeof(doh), 1, dumpfile);
169  uint8_t ipAddressBytes[4];
170  auto ipv4Address = networkInterface->getIpv4Address();
171  for (int i = 0; i < 4; i++) ipAddressBytes[i] = ipv4Address.getDByte(i);
172  fwrite(ipAddressBytes, 4, 1, dumpfile);
173  auto ipv4Netmask = networkInterface->getIpv4Netmask();
174  for (int i = 0; i < 4; i++) ipAddressBytes[i] = ipv4Netmask.getDByte(i);
175  fwrite(ipAddressBytes, 4, 1, dumpfile);
176 
177  // end of options
178  uint32_t endOfOptions = 0;
179  fwrite(&endOfOptions, sizeof(endOfOptions), 1, dumpfile);
180 
181  // trailer
182  pcapng_interface_block_trailer ibt;
183  ibt.blockTotalLength = blockTotalLength;
184  fwrite(&ibt, sizeof(ibt), 1, dumpfile);
185 }

Referenced by writePacket().

◆ writePacket()

void inet::PcapngWriter::writePacket ( simtime_t  time,
const Packet packet,
Direction  direction,
NetworkInterface ie,
PcapLinkType  linkType 
)
overridevirtual

Records the given packet into the output file if it is open, and throws an exception otherwise.

Implements inet::IPcapWriter.

188 {
189  EV_INFO << "Writing packet to file" << EV_FIELD(fileName) << EV_FIELD(packet) << EV_ENDL;
190  if (!dumpfile)
191  throw cRuntimeError("Cannot write frame: pcap output file is not open");
192 
193  auto it = interfaceModuleIdToPcapngInterfaceId.find(networkInterface->getId());
194  int pcapngInterfaceId;
195  if (it != interfaceModuleIdToPcapngInterfaceId.end())
196  pcapngInterfaceId = it->second;
197  else {
198  writeInterface(networkInterface, linkType);
199  pcapngInterfaceId = nextPcapngInterfaceId++;
200  interfaceModuleIdToPcapngInterfaceId[networkInterface->getId()] = pcapngInterfaceId;
201  }
202 
203  if (networkInterface == nullptr)
204  throw cRuntimeError("The interface entry not found for packet");
205 
206  uint32_t optionsLength = (4 + 4) + 4;
207  uint32_t blockTotalLength = 32 + roundUp(packet->getByteLength()) + optionsLength;
208  ASSERT(blockTotalLength % 4 == 0);
209 
210  // header
211  struct pcapng_packet_block_header pbh;
212  pbh.blockTotalLength = blockTotalLength;
213  pbh.interfaceId = pcapngInterfaceId;
214  pbh.timestampHigh = (int32_t)stime.inUnit(SIMTIME_S);
215  pbh.timestampLow = (uint32_t)(stime.inUnit(SIMTIME_US) - (uint32_t)1000000 * stime.inUnit(SIMTIME_S));
216  pbh.capturedPacketLength = packet->getByteLength();
217  pbh.originalPacketLength = packet->getByteLength();
218  fwrite(&pbh, sizeof(pbh), 1, dumpfile);
219 
220  // packet data
221  auto data = packet->peekDataAsBytes();
222  auto bytes = data->getBytes();
223  fwrite(bytes.data(), packet->getByteLength(), 1, dumpfile);
224 
225  // packet padding
226  char padding[] = { 0, 0, 0, 0 };
227  int paddingLength = pad(packet->getByteLength());
228  fwrite(padding, paddingLength, 1, dumpfile);
229 
230  // direction option
231  pcapng_option_header doh;
232  doh.code = 0x0002;
233  doh.length = 4;
234  uint32_t flagsOptionValue = 0;
235  switch (direction) {
236  case DIRECTION_INBOUND:
237  flagsOptionValue = 0b01;
238  break;
239  case DIRECTION_OUTBOUND:
240  flagsOptionValue = 0b10;
241  break;
242  default:
243  throw cRuntimeError("Unknown direction value");
244  }
245  fwrite(&doh, sizeof(doh), 1, dumpfile);
246  fwrite(&flagsOptionValue, sizeof(flagsOptionValue), 1, dumpfile);
247 
248  // end of options
249  uint32_t endOfOptions = 0;
250  fwrite(&endOfOptions, sizeof(endOfOptions), 1, dumpfile);
251 
252  // trailer
253  struct pcapng_packet_block_trailer pbt;
254  pbt.blockTotalLength = blockTotalLength;
255  fwrite(&pbt, sizeof(pbt), 1, dumpfile);
256 
257  if (flush)
258  fflush(dumpfile);
259 }

Member Data Documentation

◆ dumpfile

FILE* inet::PcapngWriter::dumpfile = nullptr
protected

◆ fileName

std::string inet::PcapngWriter::fileName
protected

Referenced by open(), writeInterface(), and writePacket().

◆ flush

bool inet::PcapngWriter::flush = false
protected

Referenced by open().

◆ interfaceModuleIdToPcapngInterfaceId

std::map<int, int> inet::PcapngWriter::interfaceModuleIdToPcapngInterfaceId
protected

Referenced by writePacket().

◆ nextPcapngInterfaceId

int inet::PcapngWriter::nextPcapngInterfaceId = 0
protected

Referenced by writePacket().


The documentation for this class was generated from the following files:
inet::DIRECTION_INBOUND
@ DIRECTION_INBOUND
Definition: DirectionTag_m.h:57
inet::PcapngWriter::flush
bool flush
Definition: PcapngWriter.h:26
inet::DIRECTION_OUTBOUND
@ DIRECTION_OUTBOUND
Definition: DirectionTag_m.h:58
inet::PcapngWriter::dumpfile
FILE * dumpfile
Definition: PcapngWriter.h:25
inet::PcapngWriter::interfaceModuleIdToPcapngInterfaceId
std::map< int, int > interfaceModuleIdToPcapngInterfaceId
Definition: PcapngWriter.h:28
inet::PcapngWriter::writeInterface
void writeInterface(NetworkInterface *networkInterface, PcapLinkType linkType)
Records the interface into the output file.
Definition: PcapngWriter.cc:117
EV_FIELD
#define EV_FIELD(...)
Definition: INETDefs.h:112
inet::utils::roundUp
int roundUp(int numToRound, int multiple)
Rounding up to the nearest multiple of a number.
Definition: INETUtils.h:70
inet::PcapngWriter::close
void close() override
Closes the output file if it is open.
Definition: PcapngWriter.cc:261
PCAP_MAGIC
#define PCAP_MAGIC
Definition: PcapngWriter.cc:18
inet::PcapngWriter::fileName
std::string fileName
Definition: PcapngWriter.h:24
inet::PcapngWriter::nextPcapngInterfaceId
int nextPcapngInterfaceId
Definition: PcapngWriter.h:27
EV_ENDL
#define EV_ENDL
Definition: INETDefs.h:114
inet::utils::makePathForFile
void makePathForFile(const char *filename)
Definition: INETUtils.cc:210