/*
* Copyright (c) 2017-2024 OARC, Inc.
* Copyright (c) 2011-2017, IIS - The Internet Foundation in Sweden
* All rights reserved.
*
* This file is part of PacketQ.
*
* PacketQ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PacketQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PacketQ. If not, see .
*/
#ifndef __packetq_pcap_h
#define __packetq_pcap_h
#include
#include
#include
#include "segzip.h"
#include "sql.h"
namespace packetq {
class Pcap_file {
private:
Pcap_file& operator=(const Pcap_file& other);
Pcap_file(Pcap_file&& other) noexcept;
Pcap_file const& operator=(Pcap_file&& other);
public:
static const bool TAKE_OVER_FP = true;
Pcap_file(FILE* fp, bool take_over_fp = false)
{
m_fp_owned = take_over_fp;
m_fp = fp;
m_reverse_order = false;
m_packetbuffer = 0;
m_packetbuffer_len = 0;
m_eof = false;
m_snapshot_length = 0;
m_link_layer_type = 0;
m_gzipped = false;
}
~Pcap_file()
{
if (m_packetbuffer)
delete[] m_packetbuffer;
if (m_fp_owned)
fclose(m_fp);
}
bool get_header();
unsigned char* get_packet(int& len, int& s, int& us);
int get_int32()
{
int res = 0;
get_bytes((unsigned char*)&res, 4);
if (m_reverse_order) {
return flip32(res);
}
return res;
}
int get_int16()
{
short res = 0;
get_bytes((unsigned char*)&res, 2);
if (m_reverse_order) {
return flip16(res);
}
return res;
}
unsigned char* get_bytes(int count)
{
Buffer& buf = m_gzipped ? m_zipbuffer : m_filebuffer;
if (count < buf.m_buffer_len - buf.m_buffer_pos) {
unsigned char* ptr = &buf.m_buffer[buf.m_buffer_pos];
buf.m_buffer_pos += count;
return ptr;
}
unsigned char* bufp = get_pbuffer(count + 400);
int r = get_bytes(bufp, count);
if (r == count)
return bufp;
return 0;
}
int get_bytes(unsigned char* dst, int count)
{
Buffer& buf = m_gzipped ? m_zipbuffer : m_filebuffer;
if (count == 0)
return 0;
int bytes = 0;
while (count > 0) {
if (buf.m_buffer_len == buf.m_buffer_pos) {
buffread();
if (buf.m_buffer_len == 0) {
m_eof = true;
return bytes;
}
}
int n = (buf.m_buffer_len - buf.m_buffer_pos) > count ? count : buf.m_buffer_len - buf.m_buffer_pos;
for (int i = 0; i < n; i++) {
*dst++ = buf.m_buffer[buf.m_buffer_pos++];
}
bytes += n;
count -= n;
}
return bytes;
}
void buffread()
{
if (!m_fp)
throw Error("No file");
Buffer& buf = m_filebuffer;
if (buf.m_buffer_len == buf.m_buffer_pos) {
buf.m_buffer_len = (int)fread(buf.m_buffer, 1, buf.m_nextread, m_fp);
buf.m_buffer_pos = 0;
buf.m_nextread = sizeof(buf.m_buffer);
}
if (m_gzipped) {
if (m_zip.m_error || buf.m_buffer_len == buf.m_buffer_pos) {
m_zipbuffer.m_buffer_pos = m_zipbuffer.m_buffer_len = 0;
return;
}
if (m_zipbuffer.m_buffer_len == m_zipbuffer.m_buffer_pos)
m_zip.inflate(m_filebuffer, m_zipbuffer);
}
}
void set_gzipped()
{
m_gzipped = true;
m_filebuffer.m_buffer_pos = 0;
}
int flip16(unsigned short i)
{
unsigned int r = i & 0xff;
r <<= 8;
i >>= 8;
r |= i & 0xff;
return int(r);
}
int flip32(unsigned int i)
{
unsigned int r = i & 0xff;
r <<= 8;
i >>= 8;
r |= i & 0xff;
r <<= 8;
i >>= 8;
r |= i & 0xff;
r <<= 8;
i >>= 8;
r |= i & 0xff;
return int(r);
}
unsigned char* get_pbuffer(int len)
{
if (!m_packetbuffer || len >= m_packetbuffer_len) {
if (m_packetbuffer) {
delete[] m_packetbuffer;
m_packetbuffer = 0;
}
m_packetbuffer_len = len + 4096;
m_packetbuffer = new (std::nothrow) unsigned char[m_packetbuffer_len];
if (!m_packetbuffer)
m_packetbuffer_len = 0;
}
return m_packetbuffer;
}
bool get_eof() { return m_eof; }
int get_link_layer_type() { return m_link_layer_type; }
private:
int m_snapshot_length;
int m_link_layer_type;
bool m_reverse_order;
bool m_eof;
bool m_gzipped;
FILE* m_fp;
bool m_fp_owned;
unsigned char* m_packetbuffer;
int m_packetbuffer_len;
Buffer m_filebuffer;
Buffer m_zipbuffer;
Zip m_zip;
};
} // namespace packetq
#endif // __packetq_pcap_h