]> mj.ucw.cz Git - misc.git/blob - pcap-tail.c
Merge branch 'master' of git+ssh://git.ucw.cz/home/mj/GIT/misc
[misc.git] / pcap-tail.c
1 /*
2  *      A tail-like command working on pcap files
3  *
4  *      (c) 2012 Martin Mares <mj@ucw.cz>
5  */
6
7 #define _LARGEFILE_SOURCE
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12
13 struct pcap_header {
14         uint32_t magic;
15         uint16_t major, minor;
16         uint32_t tz_offset;
17         uint32_t time_accuracy;
18         uint32_t snaplen;
19         uint32_t ll_type;
20 };
21
22 struct pcap_packet {
23         uint32_t time_sec;
24         uint32_t time_us;
25         uint32_t captured_len;
26         uint32_t orig_len;
27 };
28
29 int main(int argc, char **argv)
30 {
31         if (argc != 3) {
32                 fprintf(stderr, "Usage: pcap-tail <num-packets> <file>\n");
33                 return 1;
34         }
35
36         uint64_t num = atoi(argv[1]);
37         uint64_t *ring = malloc(num * sizeof(uint64_t));
38         if (!ring) {
39                 fprintf(stderr, "Out of memory\n");
40                 return 1;
41         }
42
43         FILE *in = fopen(argv[2], "r");
44         if (!in) {
45                 fprintf(stderr, "Cannot open %s: %m\n", argv[2]);
46                 return 1;
47         }
48
49         struct pcap_header hdr;
50         if (fread(&hdr, sizeof(hdr), 1, in) < 1) {
51                 fprintf(stderr, "Cannot read header\n");
52                 return 1;
53         }
54         if (hdr.magic != 0xa1b2c3d4) {
55                 fprintf(stderr, "Bad (black?) magic\n");
56                 return 1;
57         }
58
59         struct pcap_packet pkt;
60         int ring_pos = 0;
61         uint64_t count = 0;
62         for (;;) {
63                 uint64_t pos = ftell(in);
64                 if (fread(&pkt, sizeof(pkt), 1, in) < 1)
65                         break;
66                 // printf("@%d len=%d\n", (int)pos, pkt.captured_len);
67                 ring[ring_pos] = pos;
68                 ring_pos = (ring_pos + 1) % num;
69                 fseek(in, pkt.captured_len, SEEK_CUR);
70                 count++;
71         }
72
73         fwrite(&hdr, sizeof(hdr), 1, stdout);
74         if (count > num) {
75                 fseek(in, ring[ring_pos], SEEK_SET);
76         } else {
77                 fseek(in, ring[0], SEEK_SET);
78         }
79
80         char buf[4096];
81         int n;
82         while ((n = fread(buf, 1, sizeof(buf), in)) > 0)
83                 fwrite(buf, 1, n, stdout);
84
85         return 0;
86 }