-
Notifications
You must be signed in to change notification settings - Fork 0
/
tutorial_pcap_files.html
185 lines (175 loc) · 11.2 KB
/
tutorial_pcap_files.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
---
title: Tutorials
layout: default
section: tutorials
---
<h1><a href="tutorials.html">Tutorials</a></h1>
<h2>Part 2: Reading and writing pcap file</h2>
<p>This part explains how to read and write packets from/to pcap and pcapng files</p>
<p>Table of contents:</p>
<ul>
<li><a href="tutorial_intro.html">Part 1: Introduction and basics</a></li>
<li>Part 2: Reading and writing pcap files
<ol>
<li><a href="#intro">Introduction</a></li>
<li><a href="#read_write_packets">Reading and writing packets</a></li>
<li><a href="#append_packets">Appending packets to existing files</a></li>
<li><a href="#run_example">Running the example</a></li>
</ol>
</li>
<li><a href="tutorial_live_capture.html">Part 3: Capturing and sending packets</a></li>
<li><a href="tutorial_packet_parsing.html">Part 4: Packet parsing</a></li>
<li><a href="tutorial_packet_craft_n_edit.html">Part 5: Packet crafting and editing</a></li>
<li><a href="tutorial_dpdk.html">Part 6: Working with DPDK</a></li>
</ul>
<h2 id="intro">Introduction</h2>
<p>PcapPlusPlus supports 2 packet capture file formats: pcap and pcap-ng. Using an easy-to-use interface you can easily read and write packets from/to those file types</p>
<p>Essentialy there are 4 classes and 2 interfaces for that:</p>
<ul>
<li><strong>PcapFileReaderDevice</strong> - read packets from pcap files</li>
<li><strong>PcapNgFileReaderDevice</strong> - read packets from pcap-ng files</li>
<li><strong>PcapFileWriterDevice</strong> - write packets to a pcap file</li>
<li><strong>PcapNgFileWriterDevice</strong> - write packets to a pcap-ng file</li>
<li><strong>IFileReaderDevice</strong> - a reader interface, implemented by both PcapFileReaderDevice and PcapNgFileReaderDevice</li>
<li><strong>IFileWriterDevice</strong> - a writer interface, implemented by both PcapFileWriterDevice and PcapNgFileWriterDevice</li>
</ul>
<p>In this tutorial we'll write a simple application that reads and writes packets from/to pcap and pcap-ng file.</p>
<h2 id="read_write_packets">Reading and writing packets</h2>
<p>So let's start our application with a "main" method and a single include to "PcapFileDevice.h" which contains all the API for reading and writing packets from/to files</p>
<pre>
<code class="language-cpp">#include "stdlib.h"
#include "PcapFileDevice.h"
/**
* main method of the application
*/
int main(int argc, char* argv[])
{
// write your code here
}</code>
</pre>
<p>Next thing would be to open a pcap file for reading. We'll assume we have a pcap file named "input.pcap" and we want to open it for reading. If we know it's a pcap file we can use the pcap reader class <code class="language-cpp">PcapFileReaderDevice</code>, and same for pcap-ng files we can use <code class="language-cpp">PcapNgFileReaderDevice</code> class.</p>
<p>But PcapPlusPlus also contains an interface class that automatically identifies the file type by its extension and creates an interface instance which both classes implement, so you can use it without really knowing which class hides behind it. This interface is called <code class="language-cpp">IFileReaderDevice</code>. Let's use it in our application:</p>
<pre>
<code class="language-cpp">// use the IFileReaderDevice interface to automatically identify file type (pcap/pcap-ng)
// and create an interface instance that both readers implement
pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader("input.pcap");
// verify that a reader interface was indeed created
if (reader == NULL)
{
printf("Cannot determine reader for file type\n");
exit(1);
}</code>
</pre>
<p>As you can see we used the static method <code class="language-cpp">pcpp::IFileReaderDevice::getReader()</code> to create the interface.</p>
<p>Now let's open the reader for reading:</p>
<pre>
<code class="language-cpp">// open the reader for reading
if (!reader->open())
{
printf("Cannot open input.pcap for reading\n");
exit(1);
}</code>
</pre>
<p>Now we are ready to start reading packets from the file. But before we do that let's demonstrate using file writers as well. We'll open 2 file writers: one pcap writer and one pcap-ng writer. We'll write the packets we read from the reader to both writers.</p>
<p>Let's start by creating the pcap writer and open it for writing:</p>
<pre>
<code class="language-cpp">// create a pcap file writer. Specify file name and link type of all packets that
// will be written to it
pcpp::PcapFileWriterDevice pcapWriter("output.pcap", pcpp::LINKTYPE_ETHERNET);
// try to open the file for writing
if (!pcapWriter.open())
{
printf("Cannot open output.pcap for writing\n");
exit(1);
}</code>
</pre>
<p>As you can see we need to specify in the constructor the file name ("output.pcap") and the link type of all packets that will be written to it. That's because the pcap file format can contain single link type per file.</p>
<p>Now let's open the second writer that writes pcap-ng files:</p>
<pre>
<code class="language-cpp">// create a pcap-ng file writer. Specify file name. Link type is not necessary because
// pcap-ng files can store multiple link types in the same file
pcpp::PcapNgFileWriterDevice pcapNgWriter("output.pcapng");
// try to open the file for writing
if (!pcapNgWriter.open())
{
printf("Cannot open output.pcapng for writing\n");
exit(1);
}</code>
</pre>
<p>You can notice that in this constructor there's no need to specify the link type. That's because pcap-ng files can store multiple link types in the same file.</p>
<p>Another cool feature in file readers is setting a BPF filter so only packets that match the filter will be read and the others will be ignored. Let's set a filter that will catch only packets with source or dest IP of "98.138.19.88":</p>
<pre>
<code class="language-cpp">// set a BPF filter for the reader - only packets that match the filter will be read
if (!reader->setFilter("net 98.138.19.88"))
{
printf("Cannot set filter for file reader\n");
exit(1);
}</code>
</pre>
<p>Now let's start a while loop where we'll read all the packets (that match the BPF filter) and write them to both writers:</p>
<pre>
<code class="language-cpp">// the packet container
pcpp::RawPacket rawPacket;
// a while loop that will continue as long as there are packets in the input file
// matching the BPF filter
while (reader->getNextPacket(rawPacket))
{
// write each packet to both writers
pcapWriter.writePacket(rawPacket);
pcapNgWriter.writePacket(rawPacket);
}</code>
</pre>
<p>We're done reading all packets that match the BPF filter and writing them to both writers.</p>
<p>Another feature I'd like to demonstrate is getting reader/writer statistics. These are basic stats that only count packets that were read/written successfully and those who weren't. Let's get stats from reader and both writers and print them:</p>
<pre>
<code class="language-cpp">// create the stats object
pcap_stat stats;
// read stats from reader and print them
reader->getStatistics(stats);
printf("Read %d packets successfully and %d packets could not be read\n", stats.ps_recv, stats.ps_drop);
// read stats from pcap writer and print them
pcapWriter.getStatistics(stats);
printf("Written %d packets successfully to pcap writer and %d packets could not be written\n", stats.ps_recv, stats.ps_drop);
// read stats from pcap-ng writer and print them
pcapNgWriter.getStatistics(stats);
printf("Written %d packets successfully to pcap-ng writer and %d packets could not be written\n", stats.ps_recv, stats.ps_drop);</code>
</pre>
<p>We're done reading and writing packets. The only thing left is closing the reader and writers. We also need to free the reader because it was created by the <code class="language-cpp">pcpp::IFileReaderDevice::getReader()</code> static method.</p>
<pre>
<code class="language-cpp">// close reader
reader->close();
// close writers
pcapWriter.close();
pcapNgWriter.close();
// free reader memory because it was created by pcpp::IFileReaderDevice::getReader()
delete reader;</code>
</pre>
<p>When running the application with the input.pcap file attached below, here is the output (on Windows):</p>
<pre>
<code class="language-shell">C:\PcapPlusPlus\Examples\Tutorials\Part2-PcapFiles>Part2-PcapFiles.exe
Read 10 packets successfully and 0 packets could not be read
Written 10 packets successfully to pcap writer and 0 packets could not be written
Written 10 packets successfully to pcap-ng writer and 0 packets could not be written</code>
</pre>
<p>As you can see 10 packets were read successfully from the reader and written to both writers. Notice the original "input.pcap" file contains 28 packets, the reason not all of them were read is the BPF filter we set: only 10 out of the 28 packets matched the filter.</p>
<h2 id="append_packets">Appending packets to existing files</h2>
<p>PcapPlusPlus enables appending packets to existing pcap/pcap-ng files. This means that packets that you write won't overwrite the file but will be apppended to the existing packets in the file. This is a unique feature for PcapPlusPlus that is not supported in libpcap/WinPcap and required specific implementation outside of libpcap/WinPcap APIs. If you want to open a file writer in append mode all you need to do it to use the <code class="language-cpp">open(bool)</code> method overload and set it to "true", let's see an example:</p>
<pre>
<code class="language-cpp">// try to open the file for writing in append mode
if (!pcapWriter.open(true))
{
printf("Cannot open output.pcap for writing in append mode\n");
exit(1);
}</code>
</pre>
<p>That's it! file is now opened in append mode and will not be overriden.</p>
<h2 id="run_example">Running the example</h2>
<p>All code that was covered in this tutorial can be found <a href="https://github.com/seladb/PcapPlusPlus/tree/master/Examples/Tutorials/Tutorial-PcapFiles">here</a>. In order to compile and run the code please first download and compile PcapPlusPlus code or downloaded a pre-compiled version from <a href="https://github.com/seladb/PcapPlusPlus/releases/latest">the latest PcapPlusPlus release</a>. Then follow these instruction, according to your platform:</p>
<ul>
<li>Linux and Mac OSX - make sure PcapPlusPlus is installed (by running <strong>sudo make install</strong> in PcapPlusPlus main directory). Then either change the <code class="language-shell">Makefile.non_windows</code> file name to <code class="language-shell">Makefile</code> and run <code class="language-shell">make all</code>, or run <code class="language-shell">make -f Makefile.non_windows all</code></li>
<li>Windows using MinGW or MinGW-w64 - either change the <code class="language-shell">Makefile.windows</code> file name to <code class="language-shell">Makefile</code> and run <code class="language-shell">make all</code>, or run <code class="language-shell">make -f Makefile.windows all</code></li>
<li>Windows using Visual Studio 2015 - there is a Visual Studio 2015 solution containing all tutorials <a href="https://github.com/seladb/PcapPlusPlus/tree/master/mk/vs2015/Tutorials.sln">here</a>. Just open it and compile all tutorials</li>
</ul>
<p>In all options the compiled executable will be inside the tutorial directory (<code class="language-shell">[PcapPlusPlus Folder]/Examples/Tutorials/Tutorial-PcapFiles</code>)</p>
<script>function topFunction() { document.body.scrollTop = 0; document.documentElement.scrollTop = 0; }</script>
<p><a onclick="topFunction()" href="#">Go to top ↑</a></p>