Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 1 | """ |
| 2 | Pcap file writer |
| 3 | """ |
| 4 | |
| 5 | import struct |
| 6 | |
| 7 | PcapHeader = struct.Struct("<LHHLLLL") |
| 8 | PcapPktHeader = struct.Struct("<LLLL") |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 9 | PPIPktHeader = struct.Struct("<BBHL") |
| 10 | PPIAggregateField = struct.Struct("<HHL") |
Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 11 | |
| 12 | class PcapWriter(object): |
| 13 | def __init__(self, filename): |
| 14 | """ |
| 15 | Open a pcap file |
| 16 | """ |
| 17 | self.stream = file(filename, 'w') |
| 18 | |
| 19 | self.stream.write(PcapHeader.pack( |
| 20 | 0xa1b2c3d4, # magic |
| 21 | 2, # major |
| 22 | 4, # minor |
| 23 | 0, # timezone offset |
| 24 | 0, # timezone accuracy |
| 25 | 65535, # snapshot length |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 26 | 192 # PPI linktype |
Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 27 | )) |
| 28 | |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 29 | def write(self, data, timestamp, port): |
Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 30 | """ |
| 31 | Write a packet to a pcap file |
| 32 | |
| 33 | 'data' should be a string containing the packet data. |
| 34 | 'timestamp' should be a float. |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 35 | 'port' should be an integer port number. |
Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 36 | """ |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 37 | ppi_len = PPIPktHeader.size + PPIAggregateField.size |
Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 38 | self.stream.write(PcapPktHeader.pack( |
| 39 | int(timestamp), # timestamp seconds |
| 40 | int((timestamp - int(timestamp)) * 10**6), # timestamp microseconds |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 41 | len(data) + ppi_len, # truncated length |
| 42 | len(data) + ppi_len # un-truncated length |
Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 43 | )) |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 44 | self.stream.write(PPIPktHeader.pack( |
| 45 | 0, # version |
| 46 | 0, # flags |
| 47 | ppi_len, # length |
| 48 | 1, # ethernet dlt |
| 49 | )) |
| 50 | self.stream.write(PPIAggregateField.pack(8, PPIAggregateField.size - 4, port)) |
Rich Lane | 360bcca | 2013-08-23 17:10:14 -0700 | [diff] [blame] | 51 | self.stream.write(data) |
| 52 | |
| 53 | def close(self): |
| 54 | self.stream.close() |
Rich Lane | a9e6442 | 2013-08-26 13:56:24 -0700 | [diff] [blame^] | 55 | |
| 56 | if __name__ == "__main__": |
| 57 | import time |
| 58 | print("Writing test pcap to test.pcap") |
| 59 | pcap_writer = PcapWriter("test.pcap") |
| 60 | pcap_writer.write("\x00\x01\x02\x03\x04\x05\x00\x0a\x0b\x0c\x0d\x0e\x08\x00", time.time(), 42) |
| 61 | pcap_writer.close() |