#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pcap.h>
#include <err.h>
#include <string.h>
#include <time.h>
#include <getopt.h>

void
usage(void)
{
	fprintf(stderr, "usage: tcpdump-split [-t seconds | -n count] format\n");
	exit(1);
}

int
main(int argc, char *argv[])
{
    pcap_t *in = NULL;
    pcap_dumper_t *out = NULL;
    char errbuf[PCAP_ERRBUF_SIZE + 1];
    struct pcap_pkthdr hdr;
    int this_bin;
    int last_bin = -1;
    time_t window = 0;
    int count = 0;
    const u_char *data;
    char *fmt;
    int ch;
    uint64_t npkts = 0;

    while ((ch = getopt(argc, argv, "t:n:")) != -1) {
	switch(ch) {
	case 't':
	    window = (time_t) atoi(optarg);
	    break;
	case 'n':
	    count = atoi(optarg);
	    break;
	default:
	    usage();
	    break;
	}
    }
    argc -= optind;
    argv += optind;

    if (0 == window && 0 == count)
	usage();

    if (1 != argc)
	usage();
    fmt = strdup(argv[0]);

    in = pcap_open_offline("-", errbuf);
    if (NULL == in) {
	fprintf(stderr, "stdin: %s", errbuf);
	exit(1);
    }
    while ((data = pcap_next(in, &hdr))) {
	if (window) {
	    this_bin = hdr.ts.tv_sec - (hdr.ts.tv_sec % window);
	} else {
	    this_bin = npkts++ / count;
	}
	if (this_bin != last_bin) {
	    char fname[128];
	    if (out)
		pcap_dump_close(out);
	    if (window) {
		time_t tt = this_bin;
	        strftime(fname, 128, fmt, gmtime(&tt));
	    } else {
	        snprintf(fname, 128, fmt, this_bin);
	    }
            while (0 == access(fname, F_OK)) {
                struct timeval tvnow;
                fprintf(stderr, "tcpdump-split: will not overwrite existing %s\n", fname);
                gettimeofday(&tvnow, NULL);
                snprintf(fname, 128, "%ld.%06ld.pcap",
                        (unsigned long) tvnow.tv_sec,
                        (unsigned long) tvnow.tv_usec);
            }
	    out = pcap_dump_open(in, fname);
	    if (NULL == out) {
		perror(fname);
		exit(1);
	    }
	    last_bin = this_bin;
	}
	pcap_dump((void *)out, &hdr, data);
    }
    if (out)
	pcap_dump_close(out);
    exit(0);
}
