mirror of https://github.com/dirtbags/fluffy.git
Working pmerge command
This commit is contained in:
commit
722b3776cb
|
@ -0,0 +1,76 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
#include "pcap.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
pcap_read_header(FILE *f)
|
||||||
|
{
|
||||||
|
struct pcap_file_header h;
|
||||||
|
int swap;
|
||||||
|
|
||||||
|
if (1 != fread(&h, sizeof(h), 1, f)) {
|
||||||
|
h.magic = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MAGIC == h.magic) {
|
||||||
|
swap = 0;
|
||||||
|
} else if (bswap32(MAGIC) == h.magic) {
|
||||||
|
swap = 1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((h.version_major != 2) || (h.version_minor != 4)) return -1;
|
||||||
|
|
||||||
|
if (swap) h.snaplen = bswap32(h.snaplen);
|
||||||
|
if (h.snaplen > MAXFRAME) return -1;
|
||||||
|
|
||||||
|
return swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pcap_write_header(FILE *f)
|
||||||
|
{
|
||||||
|
struct pcap_file_header h = { MAGIC, 2, 4, 0, 0, MAXFRAME, 1 };
|
||||||
|
|
||||||
|
if (1 != fwrite(&h, sizeof(h), 1, stdout)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pcap_open_in(struct pcap_file *ctx, FILE *f)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pcap_read_header(f);
|
||||||
|
if (-1 == ret) return -1;
|
||||||
|
|
||||||
|
ctx->swap = ret;
|
||||||
|
ctx->f = f;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pcap_read_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr)
|
||||||
|
{
|
||||||
|
if (1 != fread(hdr, sizeof(*hdr), 1, ctx->f)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->swap) {
|
||||||
|
hdr->ts.tv_sec = bswap32(hdr->ts.tv_sec);
|
||||||
|
hdr->ts.tv_usec = bswap32(hdr->ts.tv_usec);
|
||||||
|
hdr->caplen = bswap32(hdr->caplen);
|
||||||
|
hdr->len = bswap32(hdr->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pcap_close(struct pcap_file *ctx)
|
||||||
|
{
|
||||||
|
fclose(ctx->f);
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef __PCAP_H__
|
||||||
|
#define __PCAP_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAGIC 0xa1b2c3d4
|
||||||
|
#define MAXFRAME 9000
|
||||||
|
|
||||||
|
struct pcap_file {
|
||||||
|
FILE *f;
|
||||||
|
int swap;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pcap_file_header {
|
||||||
|
uint32_t magic;
|
||||||
|
uint16_t version_major;
|
||||||
|
uint16_t version_minor;
|
||||||
|
int32_t thiszone; /* gmt to local correction */
|
||||||
|
uint32_t sigfigs; /* accuracy of timestamps */
|
||||||
|
int32_t snaplen; /* max length saved portion of each pkt */
|
||||||
|
int32_t linktype; /* data link type (LINKTYPE_*) */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pcap_pkthdr {
|
||||||
|
struct pcap_timeval {
|
||||||
|
uint32_t tv_sec;
|
||||||
|
uint32_t tv_usec;
|
||||||
|
} ts; /* time stamp */
|
||||||
|
uint32_t caplen; /* length of portion present */
|
||||||
|
uint32_t len; /* length this packet (off wire) */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
# define max(a, b) ((a)>(b)?(a):(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
# define min(a, b) ((a)<(b)?(a):(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define bswap32(i) (((i & 0xff000000) >> 030) | \
|
||||||
|
((i & 0x00ff0000) >> 010) | \
|
||||||
|
((i & 0x0000ff00) << 010) | \
|
||||||
|
((i & 0x000000ff) << 030))
|
||||||
|
#define bswap16(i) (((i & 0xff00) >> 010) | \
|
||||||
|
((i & 0x00ff) << 010))
|
||||||
|
|
||||||
|
|
||||||
|
/* Debugging help */
|
||||||
|
#define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args)
|
||||||
|
#define DUMP() DUMPf("")
|
||||||
|
#define DUMP_d(v) DUMPf("%s = %d", #v, v)
|
||||||
|
#define DUMP_u(v) DUMPf("%s = %u", #v, v)
|
||||||
|
#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v)
|
||||||
|
#define DUMP_s(v) DUMPf("%s = %s", #v, v)
|
||||||
|
#define DUMP_c(v) DUMPf("%s = %c", #v, v)
|
||||||
|
#define DUMP_p(v) DUMPf("%s = %p", #v, v)
|
||||||
|
|
||||||
|
int pcap_read_header(FILE *f);
|
||||||
|
int pcap_write_header(FILE *f);
|
||||||
|
int pcap_open_in(struct pcap_file *ctx, FILE *f);
|
||||||
|
int pcap_read_pkthdr(struct pcap_file *ctx, struct pcap_pkthdr *hdr);
|
||||||
|
void pcap_close(struct pcap_file *ctx);
|
||||||
|
|
||||||
|
#endif /* __PCAP_H__ */
|
|
@ -0,0 +1,129 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
#include "pcap.h"
|
||||||
|
|
||||||
|
struct input_file {
|
||||||
|
int active;
|
||||||
|
struct pcap_file p;
|
||||||
|
struct pcap_pkthdr next;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
usage(int ret)
|
||||||
|
{
|
||||||
|
printf("Usage: pmerge FILE ...\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("Merges pcap files, outputting time-ordered pcap stream\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
read_next(struct input_file *file)
|
||||||
|
{
|
||||||
|
if (! file->active) return -1;
|
||||||
|
|
||||||
|
if (-1 == pcap_read_pkthdr(&file->p, &file->next)) {
|
||||||
|
pcap_close(&file->p);
|
||||||
|
file->active = 0;
|
||||||
|
file->next.ts.tv_sec = 0xffffffff;
|
||||||
|
file->next.ts.tv_usec = 0xffffffff;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct input_file files[argc-1];
|
||||||
|
int nfiles = 0;
|
||||||
|
int nopen;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
if (1 == argc) return usage(0);
|
||||||
|
|
||||||
|
/* Open input files */
|
||||||
|
for (i = 0; i < argc-1; i += 1) {
|
||||||
|
char *fn = argv[i+1];
|
||||||
|
struct input_file *cur = &files[nfiles];
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
if ('-' == fn[0]) return usage(0);
|
||||||
|
|
||||||
|
f = fopen(fn, "rb");
|
||||||
|
if (NULL == f) {
|
||||||
|
perror(fn);
|
||||||
|
return EX_NOINPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pcap_open_in(&cur->p, f);
|
||||||
|
if (-1 == ret) {
|
||||||
|
fprintf(stderr, "%s: unable to process\n", fn);
|
||||||
|
return EX_IOERR;
|
||||||
|
}
|
||||||
|
cur->active = 1;
|
||||||
|
|
||||||
|
if (0 == read_next(cur)) {
|
||||||
|
nfiles += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pcap_write_header(stdout);
|
||||||
|
if (-1 == ret) {
|
||||||
|
perror("writing header");
|
||||||
|
return EX_IOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nopen = nfiles;
|
||||||
|
DUMP_d(nopen);
|
||||||
|
while (nopen) {
|
||||||
|
struct input_file *cur = &files[0];
|
||||||
|
char frame[MAXFRAME];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* Find next oldest frame */
|
||||||
|
for (i = 0; i < nfiles; i += 1) {
|
||||||
|
if (files[i].active &&
|
||||||
|
((files[i].next.ts.tv_sec < cur->next.ts.tv_sec) ||
|
||||||
|
((files[i].next.ts.tv_sec == cur->next.ts.tv_sec) &&
|
||||||
|
(files[i].next.ts.tv_usec < cur->next.ts.tv_usec)))) {
|
||||||
|
cur = &files[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure it'll fit */
|
||||||
|
if (cur->next.caplen > sizeof(frame)) {
|
||||||
|
fprintf(stderr, "error: huge frame (size %u)\n", len);
|
||||||
|
return EX_SOFTWARE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read it */
|
||||||
|
len = fread(frame, 1, cur->next.caplen, cur->p.f);
|
||||||
|
if (len < cur->next.caplen) {
|
||||||
|
/* Short read */
|
||||||
|
cur->next.caplen = len;
|
||||||
|
pcap_close(&cur->p);
|
||||||
|
cur->active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write header + frame */
|
||||||
|
if (len) {
|
||||||
|
if (1 != fwrite(&cur->next, sizeof(cur->next), 1, stdout)) {
|
||||||
|
perror("error");
|
||||||
|
return EX_IOERR;
|
||||||
|
}
|
||||||
|
if (len != fwrite(frame, 1, len, stdout)) {
|
||||||
|
perror("error");
|
||||||
|
return EX_IOERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 == read_next(cur)) {
|
||||||
|
nopen -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue