]> mj.ucw.cz Git - misc.git/commitdiff
New: pcap-tail
authorMartin Mares <mj@ucw.cz>
Sun, 22 Jan 2012 21:48:59 +0000 (22:48 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 22 Jan 2012 21:48:59 +0000 (22:48 +0100)
Makefile
pcap-tail.c [new file with mode: 0644]

index 5c3729f9467b10aeaa7dc1d7190a72df1e5aa1e4..f7d486df9981e65bafcb65c0abf3f878347ca030 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ parrot: parrot.c
 xclipcat: xclipcat.c
 xclipsend: xclipsend.c
 prefork: prefork.c
+pcap-tail: pcap-tail.c
 
 fft: fft.c
 fft: LDFLAGS+=-lm
diff --git a/pcap-tail.c b/pcap-tail.c
new file mode 100644 (file)
index 0000000..f4108a5
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *     A tail-like command working on pcap files
+ *
+ *     (c) 2012 Martin Mares <mj@ucw.cz>
+ */
+
+#define _LARGEFILE_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+struct pcap_header {
+       uint32_t magic;
+       uint16_t major, minor;
+       uint32_t tz_offset;
+       uint32_t time_accuracy;
+       uint32_t snaplen;
+       uint32_t ll_type;
+};
+
+struct pcap_packet {
+       uint32_t time_sec;
+       uint32_t time_us;
+       uint32_t captured_len;
+       uint32_t orig_len;
+};
+
+int main(int argc, char **argv)
+{
+       if (argc != 3) {
+               fprintf(stderr, "Usage: pcap-tail <num-packets> <file>\n");
+               return 1;
+       }
+
+       uint64_t num = atoi(argv[1]);
+       uint64_t *ring = malloc(num * sizeof(uint64_t));
+       if (!ring) {
+               fprintf(stderr, "Out of memory\n");
+               return 1;
+       }
+
+       FILE *in = fopen(argv[2], "r");
+       if (!in) {
+               fprintf(stderr, "Cannot open %s: %m\n", argv[2]);
+               return 1;
+       }
+
+       struct pcap_header hdr;
+       if (fread(&hdr, sizeof(hdr), 1, in) < 1) {
+               fprintf(stderr, "Cannot read header\n");
+               return 1;
+       }
+       if (hdr.magic != 0xa1b2c3d4) {
+               fprintf(stderr, "Bad (black?) magic\n");
+               return 1;
+       }
+
+       struct pcap_packet pkt;
+       int ring_pos = 0;
+       uint64_t count = 0;
+       for (;;) {
+               uint64_t pos = ftell(in);
+               if (fread(&pkt, sizeof(pkt), 1, in) < 1)
+                       break;
+               // printf("@%d len=%d\n", (int)pos, pkt.captured_len);
+               ring[ring_pos] = pos;
+               ring_pos = (ring_pos + 1) % num;
+               fseek(in, pkt.captured_len, SEEK_CUR);
+               count++;
+       }
+
+       fwrite(&hdr, sizeof(hdr), 1, stdout);
+       if (count > num) {
+               fseek(in, ring[ring_pos], SEEK_SET);
+       } else {
+               fseek(in, ring[0], SEEK_SET);
+       }
+
+       char buf[4096];
+       int n;
+       while ((n = fread(buf, 1, sizeof(buf), in)) > 0)
+               fwrite(buf, 1, n, stdout);
+
+       return 0;
+}