LCA2011 version
[tridge/junkcode.git] / igmp_scan.c
1 /* simple igmp scanner
2
3    Andrew Tridgell 2004
4 */
5
6 #include <stdio.h>
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <time.h>
14 #include <errno.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/ioctl.h>
18 #include <sys/time.h>
19 #include <netinet/in.h>
20 #include <netinet/ip.h>
21 #include <netinet/udp.h>
22 #include <arpa/inet.h>
23 #include <linux/if_ether.h>
24 #include <linux/if_arp.h>
25
26 #define DEBUG 0
27
28 #define MAX_PACKET_LENGTH 1600 
29 #define HISTORY_LENGTH 20
30
31 typedef unsigned char byte_t;
32
33 static void s_8(byte_t *pkt, int ofs, unsigned v)
34 {
35         pkt[ofs] = v;
36 }
37
38 static void s_16(byte_t *pkt, int ofs, unsigned v)
39 {
40         ((unsigned short *)(pkt + ofs))[0] = htons(v);
41 }
42
43 static void s_32(byte_t *pkt, int ofs, unsigned v)
44 {
45         ((unsigned *)(pkt + ofs))[0] = htonl(v);
46 }
47
48
49 static unsigned ip_sum(byte_t *data, int len)
50 {
51         int i;
52         unsigned sum = 0;
53         for (i=0;i<len;i+=2) {
54                 sum += ((unsigned short *)(data + i))[0];
55                 sum &= 0xFFFF;
56         }
57         return htons(~sum);
58 }
59
60
61 static int iface_index(const char *ifname)
62 {
63         int fd;
64         struct ifreq ifr;
65
66         if (isdigit(ifname[0])) {
67                 return atoi(ifname);
68         }
69
70         fd = socket(PF_PACKET, SOCK_DGRAM, ETH_P_IP);
71         if (fd == -1) {
72                 perror("socket");
73                 return -1;
74         }
75
76         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
77
78         if (ioctl(fd, SIOCGIFINDEX, &ifr) != 0) {
79                 perror("SIOCGIFINDEX");
80                 return -1;
81         }
82
83         close(fd);
84
85         return ifr.ifr_ifindex;
86 }
87
88
89 int main(int argc, char *argv[])
90 {
91         int fd;
92         byte_t pkt[32];
93         int ttl;
94         in_addr_t src_ip, dst_ip, group_ip;
95         struct sockaddr_ll ll;
96         unsigned count;
97         unsigned ifindex;
98
99         if (argc < 6) {
100                 printf("Usage igmp_scan <ttl> <iface> <src> <dest> <count>\n");
101                 exit(1);
102         }
103
104
105         fd = socket(PF_PACKET, SOCK_DGRAM, ETH_P_IP);
106         if (fd == -1) {
107                 perror("eth_open");
108                 exit(1);
109         }
110
111         ttl = atoi(argv[1]);
112
113         ifindex = iface_index(argv[2]);
114         if (ifindex == -1) {
115                 printf("Bad interface name '%s'\n", argv[2]);
116                 exit(1);
117         }
118
119         src_ip   = inet_addr(argv[3]);
120         dst_ip   = inet_addr(argv[4]);
121         count    = atoi(argv[5]);
122
123
124         do {
125                 group_ip = dst_ip;
126
127                 memset(pkt, 0, sizeof(pkt));
128
129                 s_8 (pkt,  0, 0x46);
130                 s_16(pkt,  2, sizeof(pkt));
131                 s_8 (pkt,  8, ttl); 
132                 s_8 (pkt,  9, 2);
133                 s_32(pkt, 12, htonl(src_ip));
134                 s_32(pkt, 16, htonl(dst_ip));
135                 s_32(pkt, 20, 0x94040000); /* router alert */
136                 
137                 s_8 (pkt, 24, 0x16); /* membership report */
138                 s_32(pkt, 28, htonl(group_ip));
139                 
140                 s_16(pkt, 26, ip_sum(pkt+24, 8)); /* igmp csum */
141                 
142                 s_16(pkt, 10, ip_sum(pkt, 32)-0x100); /* ip csum */
143                 
144                 ll.sll_family = AF_PACKET;
145                 ll.sll_protocol = htons(ETH_P_IP);
146                 ll.sll_ifindex = ifindex;
147                 ll.sll_hatype  = htons(ARPHRD_ETHER);
148                 ll.sll_pkttype = PACKET_MULTICAST;
149                 ll.sll_halen = 6;
150                 ll.sll_addr[0] = 1;
151                 ll.sll_addr[1] = 0;
152                 s_32(ll.sll_addr, 2, (0x5e<<24) | (ntohl(group_ip) & 0x7FFFFF));
153                 
154                 sendto(fd, pkt, sizeof(pkt), 0, (struct sockaddr *)&ll, sizeof(ll));
155
156                 dst_ip = htonl(ntohl(dst_ip)+1);
157                 if ((count % 10) == 0) { 
158                         usleep(1);
159                 }
160         } while (--count);
161         
162         return 0;
163 }