17 constexpr
unsigned DEBUG_VERBOSE = 0;
24 constexpr u32 BLK_PCAP_HDR1_BE = 0xA1B2C3D4;
25 constexpr u32 BLK_PCAP_HDR2_BE = 0xA1B23C4D;
26 constexpr u32 BLK_PCAP_HDR1_LE = 0xD4C3B2A1;
27 constexpr u32 BLK_PCAP_HDR2_LE = 0x4D3CB2A1;
30 constexpr u32 BLK_PCAPNG_IDB = 1;
31 constexpr u32 BLK_PCAPNG_SPB = 3;
32 constexpr u32 BLK_PCAPNG_EPB = 6;
33 constexpr u32 BLK_PCAPNG_SHB = 0x0A0D0D0Au;
34 constexpr u32 PCAPNG_MAGIC_BE = 0x1A2B3C4D;
37 constexpr
inline unsigned word_pad(
unsigned len)
38 {
return (-len) % 4; }
40 ReadPcap::ReadPcap(
const char* filename)
48 if (filename)
open(filename);
52 if (DEBUG_VERBOSE > 0)
53 Log(satcat5::log::DEBUG,
"ReadPcap::open");
56 m_file.
open(filename);
65 u32 magic = m_file.read_u32();
66 if (magic == BLK_PCAPNG_SHB) {
70 }
else if (magic == BLK_PCAP_HDR1_BE || magic == BLK_PCAP_HDR2_BE) {
74 }
else if (magic == BLK_PCAP_HDR1_LE || magic == BLK_PCAP_HDR2_LE) {
81 Log(satcat5::log::ERROR,
"ReadPcap: Invalid file");
97 }
else if (m_mode_ng) {
102 void ReadPcap::pcap_hdr() {
103 if (DEBUG_VERBOSE > 1)
104 Log(satcat5::log::DEBUG,
"ReadPcap::pcap_hdr");
108 u16 major = file_rd16();
109 u16 minor = file_rd16();
111 u32 type = file_rd32();
115 if (major == 2 && minor == 4) {
117 if (type & 0x10000000) m_trim = (type >> 29);
121 bool ReadPcap::pcap_dat() {
122 if (DEBUG_VERBOSE > 1)
123 Log(satcat5::log::DEBUG,
"ReadPcap::pcap_dat");
127 u32 clen = file_rd32();
128 u32 olen = file_rd32();
131 if (clen <= m_trim || olen <= m_trim) {
134 }
else if (olen <= clen && clen <=
sizeof(m_buff)) {
147 bool ReadPcap::pcapng_blk() {
149 switch (file_rd32()) {
150 case BLK_PCAPNG_IDB: pcapng_idb();
break;
151 case BLK_PCAPNG_SPB: pcapng_spb();
break;
152 case BLK_PCAPNG_EPB: pcapng_epb();
break;
153 case BLK_PCAPNG_SHB: pcapng_shb();
break;
154 default: pcapng_skip();
break;
161 void ReadPcap::pcapng_shb() {
162 if (DEBUG_VERBOSE > 0)
163 Log(satcat5::log::DEBUG,
"ReadPcap::pcapng_shb");
167 u32 len = m_file.read_u32();
168 u32 bom = m_file.read_u32();
171 m_mode_be = (bom == PCAPNG_MAGIC_BE);
172 if (!m_mode_be) len = __builtin_bswap32(len);
178 void ReadPcap::pcapng_idb() {
179 if (DEBUG_VERBOSE > 1)
180 Log(satcat5::log::DEBUG,
"ReadPcap::pcapng_idb");
184 u32 blen = file_rd32();
190 while (rdpos + 8 < blen) {
192 u16 opt_typ = file_rd16();
193 u16 opt_len = file_rd16();
196 if (opt_typ == 0)
break;
198 if (opt_typ == 13 && opt_len == 1) {
203 unsigned pad_len = opt_len + word_pad(opt_len);
213 void ReadPcap::pcapng_spb() {
214 if (DEBUG_VERBOSE > 1)
215 Log(satcat5::log::DEBUG,
"ReadPcap::pcapng_spb");
218 u32 blen = file_rd32();
219 u32 olen = file_rd32();
220 u32 plen = blen - 16;
223 if (blen < 16 || plen <= m_trim || olen <= m_trim) {
226 }
else if (olen <= plen && olen <=
sizeof(m_buff)) {
238 void ReadPcap::pcapng_epb() {
239 if (DEBUG_VERBOSE > 1)
240 Log(satcat5::log::DEBUG,
"ReadPcap::pcapng_epb");
244 u32 blen = file_rd32();
246 u32 clen = file_rd32();
247 u32 olen = file_rd32();
250 if (clen <= m_trim || olen <= m_trim) {
253 }
else if (olen <= clen && olen <=
sizeof(m_buff)) {
265 void ReadPcap::pcapng_skip() {
266 if (DEBUG_VERBOSE > 1)
267 Log(satcat5::log::DEBUG,
"ReadPcap::pcapng_skip");
270 u32 blen = file_rd32();
275 : satcat5::io::
ArrayWrite(m_buff, sizeof(m_buff))
279 , m_interface_count(0)
280 , m_interface_next(0)
282 m_clock.
set(posix_timer.gps());
286 if (DEBUG_VERBOSE > 0)
287 Log(satcat5::log::DEBUG,
"WritePcap::open");
290 m_file.
open(filename);
295 m_file.write_u32(BLK_PCAPNG_SHB);
296 m_file.write_u32(32);
297 m_file.write_u32(PCAPNG_MAGIC_BE);
298 m_file.write_u32(0x00010000);
299 m_file.write_u64(-1ull);
301 m_file.write_u32(32);
303 m_interface_count = 0;
307 m_file.write_u32(BLK_PCAP_HDR1_BE);
308 m_file.write_u32(0x00020004);
311 m_file.write_u32(SATCAT5_PCAP_BUFFSIZE);
313 m_file.write_u16(linktype);
319 unsigned block_len = 24, name_len = 0, name_pad = 0;
321 name_len = strlen(name);
322 name_pad = word_pad(name_len);
323 block_len += 4 + name_len + name_pad;
326 m_file.write_u32(BLK_PCAPNG_IDB);
327 m_file.write_u32(block_len);
328 m_file.write_u16(linktype);
330 m_file.write_u32(SATCAT5_PCAP_BUFFSIZE);
334 m_file.write_u16(name_len);
336 while (name_pad--) m_file.
write_u8(0);
339 m_file.write_u32(block_len);
340 return m_interface_count++;
345 constexpr u64 GPS2UNIX = 315964800000000ull;
346 u64 unix_usec = 1000 * m_clock.
now() + GPS2UNIX;
352 u32 olen = ok ? clen : UINT32_MAX;
354 if (DEBUG_VERBOSE > 1)
355 Log(satcat5::log::DEBUG,
"WritePcap::write").
write10(clen);
360 Log(satcat5::log::WARNING,
"WritePcap: Passthrough dropped (oversize).");
369 u32 plen = clen + word_pad(clen);
370 memset(m_buff + clen, 0, plen - clen);
372 m_file.write_u32(BLK_PCAPNG_EPB);
373 m_file.write_u32(36 + plen);
374 m_file.write_u32(m_interface_next);
375 m_file.write_u64(unix_usec);
376 m_file.write_u32(clen);
377 m_file.write_u32(olen);
380 m_file.write_u32(36 + plen);
382 m_interface_next = 0;
385 m_file.write_u32(unix_usec / 1000000ull);
386 m_file.write_u32(unix_usec % 1000000ull);
387 m_file.write_u32(clen);
388 m_file.write_u32(olen);
397 , m_id(pcap ? pcap->add_interface(label, type) : 0)
403 if (!m_pcap)
return false;
void set(s64 gps)
Set current GPS time.
s64 now() const
Current time as milliseconds since GPS epoch.
Ephemeral Readable interface for a simple array.
unsigned get_read_ready() const override
How many bytes can be read without blocking?
void read_reset(unsigned len)
Reset read position to the start of the backing array, and set the readable length to the specified v...
Ephemeral Writeable interface for a simple array.
unsigned written_len() const
Report total length after write_finalize() is called.
bool write_finalize() override
Mark end of frame and release temporary working data.
void open(const char *filename, unsigned len=0)
Open the specified file to read the next frame.
bool read_bytes(unsigned nbytes, void *dst)
Read 0 or more bytes into a buffer.
unsigned get_read_ready() const override
How many bytes can be read without blocking?
bool read_consume(unsigned nbytes)
Read and discard 0 or more bytes.
void write_bytes(unsigned nbytes, const void *src)
Write 0 or more bytes from a buffer.
bool write_finalize() override
Mark end of frame and release temporary working data.
void open(const char *filename)
Open the specified file.
Read packet stream from a file.
void open(const char *filename)
Open the specified file.
void read_finalize() override
Override end-of-packet handling.
u8 read_u8()
One of many functions for reading integer/floating point values, see details.
Store packet stream to a file.
u32 add_interface(const char *name, u16 type=LINKTYPE_ETHERNET)
Write a new interface description block (PCAPNG only).
void open(const char *filename, u16 type=LINKTYPE_ETHERNET)
Open the specified file, and optionally specify LinkType.
void set_interface(u32 id)
Set interface ID number for the next call to write_finalize.
WritePcap(bool pcapng=true)
Create the capture object and set PCAP or PCAPNG mode.
bool write_finalize() override
Override end-of-packet handling.
Helper object for writing capture files with multiple sources.
WritePcapInterface(satcat5::io::WritePcap *pcap, const char *label, u16 type=LINKTYPE_ETHERNET)
Constructor adds a new interface to a packet-capture.
bool write_finalize() override
Override end-of-packet handling.
virtual void write_bytes(unsigned nbytes, const void *src)
Write 0 or more bytes from a buffer.
void write_u8(u8 data)
One of many functions for writing integer/floating point values, see details.
virtual bool write_finalize()
Mark end of frame and release temporary working data.
Wrapper class for forwarding writes to another object.
The Log class creates and formats one log message.
Log & write10(s32 val)
Print integer as a decimal value with no leading zeros.
Timer object using ctime::clock().
The TimeRef API provides access to a monotonic time-counter.
File I/O for packet capture files (PCAP, PCAPNG)
Diagnostic logging to UART and/or Ethernet ports.
Miscellaneous POSIX wrappers (e.g., heap allocation, log to console...)