]> git.sesse.net Git - multicastwardrive/blob - dump-mcast.cpp
Initial checkin.
[multicastwardrive] / dump-mcast.cpp
1 #include <pcap/pcap.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/time.h>
5 #include <time.h>
6 #include <netinet/ip.h>
7 #include <arpa/inet.h>
8
9 #include <map>
10 #include <string>
11
12 using namespace std;
13
14 struct groupstats {
15         groupstats() : count(0) {}
16
17         int count;
18         struct timeval last_seen;
19 };
20 map<uint32_t, groupstats> stats;
21
22 struct timeval now;
23
24 void callback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
25 {
26         now = h->ts;
27
28         const iphdr *ip = (const iphdr *)(bytes + 16);
29         if ((ntohl(ip->daddr) & 0xe0000000) != (224u << 24) ||
30             (ntohl(ip->daddr) & 0xffffff00) == (224u << 24) ||
31             ip->daddr == 0xffffffffu ||
32             ip->protocol != 17) {
33                 return;
34         }
35
36         ++stats[ip->daddr].count;
37         stats[ip->daddr].last_seen = h->ts;
38 }
39
40 double tdiff(const timeval &a, const timeval &b)
41 {
42         return (b.tv_sec - a.tv_sec) +
43                 1e-6 * (b.tv_usec - a.tv_usec);
44 }
45
46 void cleanup()
47 {
48         for (auto it = stats.begin(); it != stats.end(); ) {
49                 if (tdiff(it->second.last_seen, now) < 1.0) {
50                         ++it;
51                         continue;
52                 }
53
54                 in_addr ip;
55                 ip.s_addr = it->first;
56                 printf("%s %d\n", inet_ntoa(ip), it->second.count);
57                 fflush(stdout);
58                 it = stats.erase(it);
59         }
60 }
61
62 int main(void)
63 {
64         char errbuf[PCAP_ERRBUF_SIZE];
65         pcap_t *pcap = pcap_create("any", NULL);
66         if (pcap == NULL) {
67                 fprintf(stderr, "pcap_create(): %s\n", errbuf);
68                 exit(1);
69         }
70
71         pcap_activate(pcap);
72
73         for ( ;; ) {
74                 pcap_dispatch(pcap, 10000, callback, NULL);
75                 cleanup();
76                 usleep(10000);
77         }
78 }