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 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
#include <math.h>
#include "pcaplite.h"
#define MAGIC_NG 0x0A0D0D0A
#define MACIG 0xA1B2C3D4
#define MAX_CAN_PACKET_SIZE 256
// some pcap format constants
#define PCAP_FILE_HEADER_LENGTH 24
#define PCAP_FRAME_HEADER_LENGTH 16
#define PCAP_CAP_FRAME_LENGTH_OFFSET 8
#define PCAP_FRAME_LENGTH_OFFSET 12
// some pcapng format constants
#define INTERFACE_DESCRITION_BLOCK 0x01
#define ENCHANCED_PACKET_BLOCK 0x06
static unsigned char pcap_buffer[MAX_CAN_PACKET_SIZE];
static pcap_t p;
pcap *pcap_open_offline(const char *filename, char *error_text, int expected_link_type) {
FILE *file;
snprintf(error_text, PCAP_ERRBUF_SIZE, "OK");
file = fopen(filename,"rb");
if (NULL == file) {
snprintf(error_text, PCAP_ERRBUF_SIZE,
"Cannot open input file");
return NULL;
}
unsigned int magic;
size_t bytes_read;
bytes_read = fread(&magic, 1, sizeof(magic), file);
if (bytes_read != sizeof(magic)) {
snprintf(error_text, PCAP_ERRBUF_SIZE, "Cannot read magic word");
fclose(file);
return (NULL);
}
if (magic != MACIG && magic != MAGIC_NG) {
snprintf(error_text, PCAP_ERRBUF_SIZE, "Not a supported format %04x", magic);
fclose(file);
return (NULL);
}
unsigned int link_type;
fseek(file, PCAP_FILE_HEADER_LENGTH - 4, SEEK_SET);
bytes_read = fread(&link_type, 1, sizeof(link_type), file);
if (bytes_read != sizeof(link_type)) {
snprintf(error_text, PCAP_ERRBUF_SIZE, "Cannot read linktype word");
fclose(file);
return (NULL);
}
if (expected_link_type >= 0) {
// Check the link type
if ((int) link_type != expected_link_type) {
snprintf(error_text, PCAP_ERRBUF_SIZE, "This link type is not supported by this decoder");
fclose(file);
return (NULL);
}
}
// set the format
// and seek past file header
if (MAGIC_NG == magic) {
p.is_ng = 1;
fseek(file, sizeof(magic), SEEK_SET);
unsigned int section_length;
bytes_read = fread(§ion_length, 1, sizeof(section_length), file);
if (bytes_read != sizeof(section_length)) {
snprintf(error_text, PCAP_ERRBUF_SIZE, "Cannot read section length");
fclose(file);
return (NULL);
}
fseek(file, section_length, SEEK_SET);
} else {
p.is_ng = 0;
fseek(file, PCAP_FILE_HEADER_LENGTH, SEEK_SET);
}
p.file = file;
return(&p);
}
const unsigned char *pcap_next_ng(pcap_t *p, struct pcap_pkthdr *h) {
// this is for ENCHANCED_PACKET_BLOCK
struct block_header {
unsigned int block_type;
unsigned int block_size;
unsigned int interface_id;
unsigned int timestamp_hi;
unsigned int timestamp_lo;
unsigned int cap_len;
unsigned int len;
} bh;
struct option_header {
unsigned short option_type;
unsigned short option_length;
} oh;
size_t bytes_read;
static double timestamp_multiplier = 0.000001; //microseconds resolution
long fpos = ftell(p->file);
do {
bytes_read = fread(&bh, 1, sizeof(bh), p->file);
if (bytes_read != sizeof(bh)) {
//probably EOF
return (NULL);
}
if (bh.block_type != ENCHANCED_PACKET_BLOCK) {
if (INTERFACE_DESCRITION_BLOCK == bh.block_type) {
// Seek to start of options part in the header
fseek(p->file, fpos + 16, SEEK_SET);
do {
bytes_read = fread(&oh, 1, sizeof(oh), p->file);
if (bytes_read != sizeof(oh)) {
//probably EOF
return (NULL);
}
// calculate option length aligned on 4 byte boundary
unsigned int option_file_length = 4*(oh.option_length/4) + ((oh.option_length%4) ? 4:0);
// read in the buffer if it's large enough or skip
if (option_file_length <= sizeof(pcap_buffer)) {
bytes_read = fread(pcap_buffer, 1, option_file_length, p->file);
if (bytes_read != option_file_length) {
//probably EOF
return (NULL);
}
//check if time resolution option
if (0x09 == oh.option_type) {
unsigned int res = *(unsigned int*)pcap_buffer;
if ((0x80000000 & res) == 0) {
timestamp_multiplier = 1/pow(10, res);
} else {
timestamp_multiplier = 1/pow(2, (res & 0x7fffffff));
}
}
} else if (fseek(p->file, option_file_length, SEEK_CUR)) {
//probably EOF
return (NULL);
}
} while(ftell(p->file) < fpos + bh.block_size - sizeof(bh.block_size));
if (fseek(p->file, sizeof(bh.block_size), SEEK_CUR)) {
//probably EOF
return (NULL);
}
}
// skip to the next block
if (fseek(p->file, fpos + bh.block_size, SEEK_SET)) {
//probably EOF
return (NULL);
}
fpos = ftell(p->file);
}
} while (bh.block_type != ENCHANCED_PACKET_BLOCK);
h->caplen = bh.cap_len;
double timestamp = ((unsigned long long)bh.timestamp_hi << 32 | bh.timestamp_lo) * timestamp_multiplier;
double fractional, integer;
fractional = modf(timestamp, &integer);
h->ts.tv_sec = (long)integer;
h->ts.tv_usec = (long)(fractional * 1000000);
bytes_read = fread(pcap_buffer, 1, h->caplen, p->file);
if (bytes_read != h->caplen) {
//probably EOF
return (NULL);
}
//seek to the next block (go back with bytes read of the block and seek fwd with the block size)
if (fseek(p->file, fpos + bh.block_size, SEEK_SET)) {
//probably EOF
return (NULL);
}
return pcap_buffer;
}
const unsigned char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
{
if (p->is_ng) {
return pcap_next_ng(p, h);
}
size_t bytes_read;
bytes_read = fread(pcap_buffer, 1, PCAP_FRAME_HEADER_LENGTH, p->file);
if (bytes_read != PCAP_FRAME_HEADER_LENGTH) {
//probably EOF
return (NULL);
}
h->ts.tv_sec = *(unsigned int*)(pcap_buffer);
h->ts.tv_usec = *(unsigned int*)(pcap_buffer + 4);
h->caplen = *(unsigned int*)(pcap_buffer + PCAP_CAP_FRAME_LENGTH_OFFSET);
h->len = *(unsigned int*)(pcap_buffer + PCAP_FRAME_LENGTH_OFFSET);
bytes_read = fread(pcap_buffer, 1, h->caplen, p->file);
if (bytes_read != h->caplen) {
//probably EOF
return (NULL);
}
return pcap_buffer;
}
void pcap_close(pcap_t *p) {
fclose(p->file);
}
|