Skip to content

Instantly share code, notes, and snippets.

@rieck
Last active August 29, 2015 14:22
Show Gist options
  • Save rieck/1a35f688affd4e5f1672 to your computer and use it in GitHub Desktop.
Save rieck/1a35f688affd4e5f1672 to your computer and use it in GitHub Desktop.
Simple tool to discard broken packets and re-synchronize a pcap dump.
/*
* Simple tool to discard broken packets and re-synchronize a pcap dump.
* (c) 2015 Konrad Rieck (konrad@mlsec.org)
* --
* Compilation: gcc -Wall -o pcapsync pcapsync.c
*/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
/* Maximum delay between two packets (24h) */
int max_pkt_delay = 60 * 60 * 24;
/* Maximum packet size (0xffff) */
int max_pkt_size = 0xffff;
/* Name of input pcap dump */
char *pcap_in;
/* Name of output pcap dump */
char *pcap_out;
/* File header adapted from pcap.h */
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 */
uint32_t snaplen; /* max length saved portion of each pkt */
uint32_t linktype; /* data link type (LINKTYPE_*) */
};
/* Packet header adapted from pcap.h */
struct pcap_pkt_hdr {
uint32_t ts_sec; /* time stamp */
uint32_t ts_usec;
uint32_t caplen; /* length of portion present */
uint32_t len; /* length of this packet (off wire) */
};
/* Print usage of the tool */
void print_usage()
{
printf("Usage: pcapsync [-d delay] [-s size] pcap-in pcap-out\n"
" -d delay Maximum packet delay in seconds (Default: %d)\n"
" -s size Maximum packet size in bytes (Default: %d)\n",
max_pkt_delay, max_pkt_size);
}
/* Parse options using getopt(2) */
void parse_args(int argc, char **argv)
{
int ch;
while ((ch = getopt(argc, argv, "d:s:")) != -1) {
switch (ch) {
case 'd':
max_pkt_delay = atoi(optarg);
break;
case 's':
max_pkt_size = atoi(optarg);
break;
case 'h':
default:
print_usage();
exit(EXIT_FAILURE);
}
}
argc -= optind;
argv += optind;
/* Get file names */
if (argc != 2) {
print_usage();
exit(EXIT_FAILURE);
} else {
pcap_in = argv[0];
pcap_out = argv[1];
}
}
/* Sanity check on file header */
int check_header(struct pcap_file_header *hdr)
{
if (hdr->magic == 0xd4c3b2a1) {
fprintf(stderr, "%s: Wrong endianess\n", pcap_in);
return 0;
}
if (hdr->magic != 0xa1b2c3d4) {
fprintf(stderr, "%s: Invalid file header\n", pcap_in);
return 0;
}
return 1;
}
/* Sanity checks on packet header */
int check_packet(struct pcap_pkt_hdr *pkt)
{
static uint32_t last = 0;
/* Get time of first packet */
if (last == 0)
last = pkt->ts_sec;
/* Sanity check on header */
if (pkt->caplen > max_pkt_size)
return 0;
if (pkt->caplen > pkt->len)
return 0;
if (abs(last - pkt->ts_sec) > max_pkt_delay)
return 0;
/* Store timestamp */
last = pkt->ts_sec;
return 1;
}
/* Main function */
int main(int argc, char **argv)
{
FILE *in = NULL, *out = NULL;
int ret;
char *data, buf[256];
struct pcap_pkt_hdr *pkt = (struct pcap_pkt_hdr *) buf;
struct pcap_file_header *hdr = (struct pcap_file_header *) buf;
/* Parse arguments */
parse_args(argc, argv);
/* Allocate memory */
data = malloc(max_pkt_size);
if (!data) {
fprintf(stderr, "Could not allocate memory");
return EXIT_FAILURE;
}
/* Open input and output file */
in = fopen(pcap_in, "r");
out = fopen(pcap_out, "w");
if (!in || !out) {
perror(in ? pcap_out : pcap_in);
return EXIT_FAILURE;
}
/* Read file header */
ret = fread(hdr, sizeof(struct pcap_file_header), 1, in);
if (ret != 1) {
perror(pcap_in);
return EXIT_FAILURE;
}
if (!check_header(hdr))
return EXIT_FAILURE;
/* Write file header */
ret = fwrite(hdr, sizeof(struct pcap_file_header), 1, out);
if (ret != 1) {
perror(pcap_out);
return EXIT_FAILURE;
}
while (!feof(in)) {
/* Attempt to read packet */
ret = fread(pkt, sizeof(struct pcap_pkt_hdr), 1, in);
if (ret != 1)
continue;
/* Check packet for sanity and move on on error */
if (!check_packet(pkt)) {
fseek(in, 1 - sizeof(struct pcap_pkt_hdr), SEEK_CUR);
continue;
}
/* Read packet payload */
ret = fread(data, pkt->caplen, 1, in);
if (ret != 1) {
perror(pcap_in);
continue;
}
/* Write out packet */
ret = fwrite(buf, sizeof(struct pcap_pkt_hdr), 1, out);
ret += fwrite(data, pkt->caplen, 1, out);
if (ret != 2)
perror(pcap_out);
}
/* Cean up */
free(data);
fclose(out);
fclose(in);
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment