1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author:  Craig Dowell (craigdo@ee.washington.edu)
19  */
20 
21 #ifndef PCAP_FILE_H
22 #define PCAP_FILE_H
23 
24 #include <string>
25 #include <fstream>
26 #include <stdint.h>
27 #include "ns3/ptr.h"
28 
29 namespace ns3 {
30 
31 class Packet;
32 class Header;
33 
34 
35 /**
36  * \brief A class representing a pcap file
37  *
38  * A class representing a pcap file.  This allows easy creation, writing and
39  * reading of files composed of stored packets; which may be viewed using
40  * standard tools.
41  */
42 class PcapFile
43 {
44 public:
45   static const int32_t  ZONE_DEFAULT    = 0;           /**< Time zone offset for current location */
46   static const uint32_t SNAPLEN_DEFAULT = 65535;       /**< Default value for maximum octets to save per packet */
47 
48 public:
49   PcapFile ();
50   ~PcapFile ();
51 
52   /**
53    * \return true if the 'fail' bit is set in the underlying iostream, false otherwise.
54    */
55   bool Fail (void) const;
56   /**
57    * \return true if the 'eof' bit is set in the underlying iostream, false otherwise.
58    */
59   bool Eof (void) const;
60   /**
61    * Clear all state bits of the underlying iostream.
62    */
63   void Clear (void);
64 
65   /**
66    * Create a new pcap file or open an existing pcap file.  Semantics are
67    * similar to the stdc++ io stream classes, but differ in that
68    * positions in the file are based on packets not characters.  For example
69    * if the file is opened for reading, the file position indicator (seek
70    * position) points to the beginning of the first packet in the file, not
71    * zero (which would point to the start of the pcap header).
72    *
73    * Since a pcap file is always a binary file, the file type is automatically
74    * selected as a binary file (fstream::binary is automatically ored with the mode
75    * field).
76    *
77    * \param filename String containing the name of the file.
78    *
79    * \param mode the access mode for the file.
80    */
81   void Open (std::string const &filename, std::ios::openmode mode);
82 
83   /**
84    * Close the underlying file.
85    */
86   void Close (void);
87 
88   /**
89    * Initialize the pcap file associated with this object.  This file must have
90    * been previously opened with write permissions.
91    *
92    * \param dataLinkType A data link type as defined in the pcap library.  If
93    * you want to make resulting pcap files visible in existing tools, the
94    * data link type must match existing definitions, such as PCAP_ETHERNET,
95    * PCAP_PPP, PCAP_80211, etc.  If you are storing different kinds of packet
96    * data, such as naked TCP headers, you are at liberty to locally define your
97    * own data link types.  According to the pcap-linktype man page, "well-known"
98    * pcap linktypes range from 0 to 263.  If you use a large random number for
99    * your type, chances are small for a collision.
100    *
101    * \param snapLen An optional maximum size for packets written to the file.
102    * Defaults to 65535.  If packets exceed this length they are truncated.
103    *
104    * \param timeZoneCorrection An integer describing the offset of your local
105    * time zone from UTC/GMT.  For example, Pacific Standard Time in the US is
106    * GMT-8, so one would enter -8 for that correction.  Defaults to 0 (UTC).
107    *
108    * \param swapMode Flag indicating a difference in endianness of the
109    * writing system. Defaults to false.
110    *
111    * \param nanosecMode Flag indicating the time resolution of the writing
112    * system. Default to false.
113    *
114    * \warning Calling this method on an existing file will result in the loss
115    * any existing data.
116    */
117   void Init (uint32_t dataLinkType,
118              uint32_t snapLen = SNAPLEN_DEFAULT,
119              int32_t timeZoneCorrection = ZONE_DEFAULT,
120              bool swapMode = false,
121              bool nanosecMode = false);
122 
123   /**
124    * \brief Write next packet to file
125    *
126    * \param tsSec       Packet timestamp, seconds
127    * \param tsUsec      Packet timestamp, microseconds
128    * \param data        Data buffer
129    * \param totalLen    Total packet length
130    *
131    */
132   void Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, uint32_t totalLen);
133 
134   /**
135    * \brief Write next packet to file
136    *
137    * \param tsSec       Packet timestamp, seconds
138    * \param tsUsec      Packet timestamp, microseconds
139    * \param p           Packet to write
140    *
141    */
142   void Write (uint32_t tsSec, uint32_t tsUsec, Ptr<const Packet> p);
143   /**
144    * \brief Write next packet to file
145    *
146    * \param tsSec       Packet timestamp, seconds
147    * \param tsUsec      Packet timestamp, microseconds
148    * \param header      Header to write, in front of packet
149    * \param p           Packet to write
150    *
151    */
152   void Write (uint32_t tsSec, uint32_t tsUsec, const Header &header, Ptr<const Packet> p);
153 
154 
155   /**
156    * \brief Read next packet from file
157    *
158    * \param data        [out] Data buffer
159    * \param maxBytes    Allocated data buffer size
160    * \param tsSec       [out] Packet timestamp, seconds
161    * \param tsUsec      [out] Packet timestamp, microseconds
162    * \param inclLen     [out] Included length
163    * \param origLen     [out] Original length
164    * \param readLen     [out] Number of bytes read
165    *
166    */
167   void Read (uint8_t * const data,
168              uint32_t maxBytes,
169              uint32_t &tsSec,
170              uint32_t &tsUsec,
171              uint32_t &inclLen,
172              uint32_t &origLen,
173              uint32_t &readLen);
174 
175   /**
176    * \brief Get the swap mode of the file.
177    *
178    * Pcap files use a magic number that is overloaded to identify both the
179    * format of the file itself and the byte ordering of the file.  The magic
180    * number (and all data) is written into the file according to the native
181    * byte ordering of the writing system.  If a reading application reads
182    * the magic number identically (for example 0xa1b2c3d4) then no byte
183    * swapping is required to correctly interpret the file data.  If the reading
184    * application sees the magic number is byte swapped (for example 0xd4c3b2a1)
185    * then it knows that it needs to byteswap appropriate fields in the format.
186    *
187    * GetSWapMode returns a value indicating whether or not the fields are being
188    * byteswapped.  Used primarily for testing the class itself, but may be
189    * useful as a flag indicating a difference in endianness of the writing
190    * system.
191    *
192    * \returns swap mode of the file
193    */
194   bool GetSwapMode (void);
195 
196   /**
197    * \brief Get the nanosecond mode of the file.
198    *
199    * \returns true if the packet timestamps in the PCAP
200    * file have nanosecond resolution.
201    */
202    bool IsNanoSecMode (void);
203 
204   /**
205    * \brief Returns the magic number of the pcap file as defined by the magic_number
206    * field in the pcap global header.
207    *
208    * See http://wiki.wireshark.org/Development/LibpcapFileFormat
209    *
210    * \returns magic number
211    */
212   uint32_t GetMagic (void);
213 
214   /**
215    * \brief Returns the major version of the pcap file as defined by the version_major
216    * field in the pcap global header.
217    *
218    * See http://wiki.wireshark.org/Development/LibpcapFileFormat
219    *
220    * \returns major version
221    */
222   uint16_t GetVersionMajor (void);
223 
224   /**
225    * \brief Returns the minor version of the pcap file as defined by the version_minor
226    * field in the pcap global header.
227    *
228    * See http://wiki.wireshark.org/Development/LibpcapFileFormat
229    *
230    * \returns minor version
231    */
232   uint16_t GetVersionMinor (void);
233 
234   /**
235    * \brief Returns the time zone offset of the pcap file as defined by the thiszone
236    * field in the pcap global header.
237    *
238    * See http://wiki.wireshark.org/Development/LibpcapFileFormat
239    *
240    * \returns time zone offset
241    */
242   int32_t GetTimeZoneOffset (void);
243 
244   /**
245    * \brief Returns the accuracy of timestamps field of the pcap file as defined
246    * by the sigfigs field in the pcap global header.
247    *
248    * See http://wiki.wireshark.org/Development/LibpcapFileFormat
249    *
250    * \returns accuracy of timestamps
251    */
252   uint32_t GetSigFigs (void);
253 
254   /**
255    * \brief Returns the max length of saved packets field of the pcap file as
256    * defined by the snaplen field in the pcap global header.
257    *
258    * See http://wiki.wireshark.org/Development/LibpcapFileFormat
259    *
260    * \returns max length of saved packets field
261    */
262   uint32_t GetSnapLen (void);
263 
264   /**
265    * \brief Returns the data link type field of the pcap file as defined by the
266    * network field in the pcap global header.
267    *
268    * See http://wiki.wireshark.org/Development/LibpcapFileFormat
269    *
270    * \returns data link type field
271    */
272   uint32_t GetDataLinkType (void);
273 
274   /**
275    * \brief Compare two PCAP files packet-by-packet
276    *
277    * \return true if files are different, false otherwise
278    *
279    * \param  f1         First PCAP file name
280    * \param  f2         Second PCAP file name
281    * \param  sec        [out] Time stamp of first different packet, seconds. Undefined if files doesn't differ.
282    * \param  usec       [out] Time stamp of first different packet, microseconds. Undefined if files doesn't differ.
283    * \param  packets    [out] Number of first different packet. Total number of parsed packets if files doesn't differ.
284    * \param  snapLen    Snap length (if used)
285    */
286   static bool Diff (std::string const & f1, std::string const & f2,
287                     uint32_t & sec, uint32_t & usec, uint32_t & packets,
288                     uint32_t snapLen = SNAPLEN_DEFAULT);
289 
290 private:
291   /**
292    * \brief Pcap file header
293    */
294   typedef struct {
295     uint32_t m_magicNumber;   /**< Magic number identifying this as a pcap file */
296     uint16_t m_versionMajor;  /**< Major version identifying the version of pcap used in this file */
297     uint16_t m_versionMinor;  /**< Minor version identifying the version of pcap used in this file */
298     int32_t  m_zone;          /**< Time zone correction to be applied to timestamps of packets */
299     uint32_t m_sigFigs;       /**< Unused by pretty much everybody */
300     uint32_t m_snapLen;       /**< Maximum length of packet data stored in records */
301     uint32_t m_type;          /**< Data link type of packet data */
302   } PcapFileHeader;
303 
304   /**
305    * \brief Pcap record header
306    */
307   typedef struct {
308     uint32_t m_tsSec;         /**< seconds part of timestamp */
309     uint32_t m_tsUsec;        /**< microseconds part of timestamp (nsecs for PCAP_NSEC_MAGIC) */
310     uint32_t m_inclLen;       /**< number of octets of packet saved in file */
311     uint32_t m_origLen;       /**< actual length of original packet */
312   } PcapRecordHeader;
313 
314   /**
315    * \brief Swap a value byte order
316    * \param val the value
317    * \returns the value with byte order swapped
318    */
319   uint8_t Swap (uint8_t val);
320   /**
321    * \brief Swap a value byte order
322    * \param val the value
323    * \returns the value with byte order swapped
324    */
325   uint16_t Swap (uint16_t val);
326   /**
327    * \brief Swap a value byte order
328    * \param val the value
329    * \returns the value with byte order swapped
330    */
331   uint32_t Swap (uint32_t val);
332   /**
333    * \brief Swap the byte order of a Pcap file header
334    * \param from original file header
335    * \param to swapped file header
336    */
337   void Swap (PcapFileHeader *from, PcapFileHeader *to);
338   /**
339    * \brief Swap the byte order of a Pcap record header
340    * \param from original record header
341    * \param to swapped record header
342    */
343   void Swap (PcapRecordHeader *from, PcapRecordHeader *to);
344 
345   /**
346    * \brief Write a Pcap file header
347    */
348   void WriteFileHeader (void);
349   /**
350    * \brief Write a Pcap packet header
351    *
352    * The pcap header has a fixed length of 24 bytes. The last 4 bytes
353    * represent the link-layer type
354    *
355    * \param tsSec Time stamp (seconds part)
356    * \param tsUsec Time stamp (microseconds part)
357    * \param totalLen total packet length
358    * \returns the length of the packet to write in the Pcap file
359    */
360   uint32_t WritePacketHeader (uint32_t tsSec, uint32_t tsUsec, uint32_t totalLen);
361 
362   /**
363    * \brief Read and verify a Pcap file header
364    */
365   void ReadAndVerifyFileHeader (void);
366 
367   std::string    m_filename;    //!< file name
368   std::fstream   m_file;        //!< file stream
369   PcapFileHeader m_fileHeader;  //!< file header
370   bool m_swapMode;              //!< swap mode
371   bool m_nanosecMode;           //!< nanosecond timestamp mode
372 };
373 
374 } // namespace ns3
375 
376 #endif /* PCAP_FILE_H */
377