Split grml-scripts into grml-scripts and grml-scripts-core
[grml-scripts.git] / compile / pong.c
1 /*
2  * By Patrick Reynolds <reynolds@cs.duke.edu>
3  * Distributed under GPL.
4  *
5  * Build instructions
6  *   gcc pong.c -o pong
7  *
8  * Usage:
9  *   pong 1.2.3.0     # as root!
10  */
11
12 #include <errno.h>
13 #include <signal.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <arpa/inet.h>
18 #include <netinet/in.h>
19 #include <netinet/ip_icmp.h>
20 #include <sys/socket.h>
21
22 #define PONG_DEAD 0
23 #define PONG_BROKEN 1
24 #define PONG_OKAY 2
25
26 #undef I_CARE_ABOUT_BAD_RETURN_PACKETS
27
28 int id, sock;
29 int datalen = 0;
30 int nhosts = 256;
31 int vec[256];
32 int foo_set = 0;
33 struct sockaddr_in dest;
34
35 void pong();
36 void catch();
37 int in_cksum(u_short *addr, int len);
38 void print();
39 void foo(int i) { foo_set = 1; }
40
41 int main(int argc, char **argv) {
42   id = getpid();
43   if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
44     perror("pong: socket");
45     return -1;
46   }
47   if (argc != 2) {
48     fprintf(stderr, "Usage:\n  %s aaa.bbb.ccc.0\n\n", argv[0]);
49     return -1;
50   }
51   bzero(&dest, sizeof(dest));
52   dest.sin_family = AF_INET;
53   inet_aton(argv[1], &dest.sin_addr);
54   pong();
55   catch();
56   print();
57   return 0;
58 }
59
60 void pong() {
61   unsigned char buf[sizeof(struct icmphdr)];
62   struct icmphdr *p = (struct icmphdr *)buf;
63   int ret, i;
64
65         fprintf(stderr, "Sending packets");
66
67   p->type = ICMP_ECHO;
68   p->code = 0;
69   p->checksum = 0;
70   p->un.echo.sequence = 0;
71   p->un.echo.id = id;
72
73   p->checksum = in_cksum((u_short *)p, datalen + 8);
74
75   dest.sin_addr.s_addr &= 0xffffff;
76   for (i=1; i<=254; i++) {
77                 fputc('.', stderr);
78                 fflush(stderr);
79     dest.sin_addr.s_addr &= 0xffffff;
80     dest.sin_addr.s_addr |= (i<<24);
81     ret = sendto(sock, (char *)buf, 8 + datalen, 0,
82       (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
83     if (ret != 8 + datalen) {
84       if (ret < 0)
85         perror("pong: sendto");
86       printf("pong: wrote %d chars, ret=%d\n", 8+datalen, ret);
87     }
88   }
89         fputc('\n', stderr);
90 }
91
92 void catch() {
93   int ret;
94   char incoming[128];
95         fprintf(stderr, "Gathering responses");
96   bzero(vec, nhosts*sizeof(int));
97   alarm(5);
98   signal(SIGALRM, foo);
99   signal(SIGINT, foo);
100   while (!foo_set) {
101     struct sockaddr_in from;
102                 fd_set rfds;
103                 struct timeval tv = { 1, 0 };
104     socklen_t fromlen = sizeof(from);
105                 FD_ZERO(&rfds);
106                 FD_SET(sock, &rfds);
107                 if (select(sock+1, &rfds, NULL, NULL, &tv) <= 0) continue;
108     ret = recvfrom(sock, (char *)incoming, 128, 0, (struct sockaddr *)&from,
109       &fromlen);
110 #ifdef I_CARE_ABOUT_BAD_RETURN_PACKETS
111     if (ret != datalen + 16 && (ret >= 0 || errno != EINTR)) {
112       if (ret < 0)
113         perror("pong: recvfrom");
114       else
115         vec[from.sin_addr.s_addr >> 24] = PONG_BROKEN;
116       printf("pong: read %d chars, ret=%d, host=%d\n", 16+datalen, ret,
117         from.sin_addr.s_addr>>24);
118     }
119     else
120 #endif
121                 {
122                         fputc('.', stderr);
123                         fflush(stderr);
124       vec[from.sin_addr.s_addr >> 24] = PONG_OKAY;
125                 }
126   }
127         fputc('\n', stderr);
128 }
129
130 int in_cksum(u_short *addr, int len) {
131   register int nleft = len;
132   register u_short *w = addr;
133   register int sum = 0;
134   u_short answer = 0;
135         
136   while (nleft > 1)  {
137     sum += *w++;
138     nleft -= 2;
139   }
140   if (nleft == 1) {
141     *(u_char *)(&answer) = *(u_char *)w ;
142     sum += answer;
143   }
144   sum = (sum >> 16) + (sum & 0xffff);
145   sum += (sum >> 16);
146   answer = ~sum;
147   return(answer);
148 }
149
150 void print() {
151   int i, count = 0;
152   for (i=0; i<=255; i++)
153     if (vec[i]) {
154       unsigned int ip = ntohl(dest.sin_addr.s_addr);
155       count++;
156       printf("%d.%d.%d.%d: %s\n", ip>>24, (ip>>16)&0xff, (ip>>8)&0xff, i,
157         vec[i]==PONG_OKAY ? "found" : "broken");
158     }
159   printf("\nTotal hosts: %d\n", count);
160 }