Merge branch 'vendor/OPENSSL'
[dragonfly.git] / tools / tools / net80211 / wesside / dics / dics.c
1 /*-
2  * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/tools/tools/net80211/wesside/dics/dics.c,v 1.1 2006/08/07 00:05:03 sam Exp $
27  */
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/select.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <string.h>
39 #define __FAVOR_BSD
40 #include <netinet/udp.h>
41
42 #if 0
43 #include <pcap.h>
44 #endif
45
46 #define MAGIC_LEN (20+8+5)
47
48 #define PRGA_LEN (1500-14-20-8)
49
50 #define BSD
51 #define LINUX
52
53 #ifdef LINUX
54 struct ippseudo {
55         struct  in_addr ippseudo_src;   /* source internet address */
56         struct  in_addr ippseudo_dst;   /* destination internet address */
57         u_char          ippseudo_pad;   /* pad, must be zero */
58         u_char          ippseudo_p;     /* protocol */
59         u_short         ippseudo_len;   /* protocol length */
60 };
61 #endif
62
63 #define DPORT 6969
64 #define TTLSENT 128
65
66 int pps = 10;
67 int poll_rate =5;
68
69 /********** RIPPED
70 ************/
71 unsigned short in_cksum (unsigned short *ptr, int nbytes) {
72   register long sum;
73   u_short oddbyte;
74   register u_short answer;
75
76   sum = 0;
77   while (nbytes > 1)
78     {
79       sum += *ptr++;
80       nbytes -= 2;
81     }
82
83   if (nbytes == 1)
84     {
85       oddbyte = 0;
86       *((u_char *) & oddbyte) = *(u_char *) ptr;
87       sum += oddbyte;
88     }
89
90   sum = (sum >> 16) + (sum & 0xffff);
91   sum += (sum >> 16);
92   answer = ~sum;
93   return (answer);
94 }
95 /**************
96 ************/
97
98 void hexdump(unsigned char *ptr, int len) {
99         while(len > 0) {
100                 printf("%.2X ", *ptr);
101                 ptr++; len--;
102         }
103         printf("\n");
104 }
105
106 int check_signal(int s, char* ip, unsigned char* ttl, unsigned short* port) {
107         unsigned char buf[1024];
108         int rd;
109         struct msghdr msg;
110         struct iovec iv;
111         struct sockaddr_in s_in;
112         struct {
113                 struct cmsghdr hdr;
114                 unsigned char ttl;
115         } ctl;
116
117         iv.iov_base = buf;
118         iv.iov_len = sizeof(buf);
119
120         memset(&msg, 0, sizeof(msg));
121         memset(&ctl, 0, sizeof(ctl));
122         msg.msg_name = &s_in;
123         msg.msg_namelen = sizeof(s_in);
124         msg.msg_iov = &iv;
125         msg.msg_iovlen = 1;
126         msg.msg_control = &ctl;
127         msg.msg_controllen = sizeof(ctl);
128
129         rd = recvmsg(s, &msg, 0);
130         if (rd == -1) {
131                 perror("recvmsg()");
132                 exit(1);
133         }
134
135         if (rd != 5)
136                 return 0;
137
138         if ( ctl.hdr.cmsg_level != IPPROTO_IP ||
139 #ifdef LINUX
140             ctl.hdr.cmsg_type != IP_TTL
141 #else
142             ctl.hdr.cmsg_type != IP_RECVTTL
143 #endif
144             ) {
145
146             printf("Didn't get ttl! len=%d level=%d type=%d\n",
147                    ctl.hdr.cmsg_len, ctl.hdr.cmsg_level, ctl.hdr.cmsg_type);
148             exit(1);
149         }
150
151         if (memcmp(buf, "sorbo", 5) != 0)
152                 return 0;
153
154         strcpy(ip, inet_ntoa(s_in.sin_addr));
155         *ttl = ctl.ttl;
156         *port = ntohs(s_in.sin_port);
157         return 1;
158 }
159
160 #if 0
161 int check_signal(const unsigned char* buf, int rd,
162                  char* ip, char* ttl, unsigned short *port) {
163         int got_it;
164         struct ip* iph;
165         struct udphdr* uh;
166
167         if (rd != MAGIC_LEN)
168                 return 0;
169
170         iph = (struct ip*) buf;
171         uh = (struct udphdr*) ((char*)iph + 20);
172
173         if ( htons(uh->uh_dport) != DPORT)
174                 return 0;
175
176         got_it = memcmp(&buf[rd-5], "sorbo", 5) == 0;
177
178         strcpy(ip, inet_ntoa(iph->ip_src));
179         *ttl = iph->ip_ttl;
180
181         *port = ntohs(uh->uh_sport);
182         return got_it;
183 }
184 #endif
185
186 unsigned int udp_checksum(unsigned char *stuff0, int len, struct in_addr *sip,
187                           struct in_addr *dip) {
188         unsigned char *stuff;
189         struct ippseudo *ph;
190
191         stuff = (unsigned char*) malloc(len + sizeof(struct ippseudo));
192         if(!stuff) {
193                 perror("malloc()");
194                 exit(1);
195         }
196
197         ph = (struct ippseudo*) stuff;
198
199         memcpy(&ph->ippseudo_src, sip, 4);
200         memcpy(&ph->ippseudo_dst, dip, 4);
201         ph->ippseudo_pad =  0;
202         ph->ippseudo_p = IPPROTO_UDP;
203         ph->ippseudo_len = htons(len);
204
205         memcpy(stuff + sizeof(struct ippseudo), stuff0, len);
206
207         return in_cksum((unsigned short*)stuff, len+sizeof(struct ippseudo));
208 }
209
210 void send_stuff(int s, char* sip, char* ip, unsigned short port, int dlen) {
211         static unsigned char buf[PRGA_LEN+128] = "\x69";
212         static int plen = 0;
213         static struct sockaddr_in dst;
214         int rd;
215         struct in_addr tmp_dst;
216         int stuff, delay;
217         int i;
218
219         stuff = poll_rate*pps;
220         delay = (int) ((double)1.0/pps*1000.0*1000.0);
221
222         inet_aton(ip, &tmp_dst);
223         if (tmp_dst.s_addr != dst.sin_addr.s_addr ||
224             dlen != (plen - 20 - 8)) {
225
226             buf[0] = '\x69';
227         }
228
229         // create packet
230         if (buf[0] == '\x69') {
231                 struct ip* iph;
232                 struct udphdr* uh;
233                 char* ptr;
234
235 //              printf("Initializing packet...\n");
236                 memset(buf, 0, sizeof(buf));
237                 iph = (struct ip*) buf;
238                 iph->ip_hl = 5;
239                 iph->ip_v = 4;
240                 iph->ip_tos = 0;
241                 iph->ip_len = htons(20+8+dlen);
242                 iph->ip_id = htons(666);
243                 iph->ip_off = 0;
244                 iph->ip_ttl = TTLSENT;
245                 iph->ip_p = IPPROTO_UDP;
246                 iph->ip_sum = 0;
247
248                 inet_aton(sip, &iph->ip_src);
249                 inet_aton(ip, &iph->ip_dst);
250
251                 memset(&dst, 0, sizeof(dst));
252                 dst.sin_family = PF_INET;
253                 dst.sin_port = htons(port);
254                 memcpy(&dst.sin_addr, &iph->ip_dst, sizeof(dst.sin_addr));
255
256                 iph->ip_sum = in_cksum((unsigned short*)iph, 20);
257
258                 uh = (struct udphdr*) ((char*)iph + 20);
259                 uh->uh_sport = htons(DPORT);
260                 uh->uh_dport = htons(port);
261                 uh->uh_ulen = htons(8+dlen);
262                 uh->uh_sum = 0;
263
264                 ptr = (char*) uh + 8;
265
266                 memset(ptr, 0, dlen);
267
268                 uh->uh_sum = udp_checksum((unsigned char*)uh, 8+dlen,
269                                           &iph->ip_src, &iph->ip_dst);
270
271 #ifdef BSD
272                 iph->ip_len = ntohs(iph->ip_len);
273 #endif
274                 plen = 20+8+dlen;
275         }
276 #if 0
277         printf("Packet %d %s %d\n", plen, inet_ntoa(dst.sin_addr),
278         ntohs(dst.sin_port));
279         hexdump (buf, plen);
280 #endif
281
282 //      printf("sending stuff to %s\n", ip);
283         for (i = 0; i < stuff; i++) {
284                 rd = sendto(s, buf, plen, 0, (struct sockaddr*)&dst, sizeof(dst));
285                 if (rd == -1) {
286                         perror("sendto()");
287                         exit(1);
288                 }
289                 if (rd != plen) {
290                         printf("wrote %d out of %d\n", rd, plen);
291                         exit(1);
292                 }
293
294                 // sending ttl..
295                 if (dlen != PRGA_LEN)
296                         break;
297                 usleep(delay);
298         }
299 }
300
301 int main(int argc, char *argv[]) {
302         int s, us;
303         int rd = 1;
304
305 #if 0
306         const u_char* buf;
307         char errbuf[PCAP_ERRBUF_SIZE];
308         struct pcap_pkthdr phdr;
309         pcap_t* p;
310         int dtl;
311 #endif
312
313         int got_it = 0;
314         char ip[16] = "\x00";
315         unsigned char ttl = 0;
316         unsigned short port;
317         struct sockaddr_in s_in;
318         struct timeval tv;
319         fd_set rfds;
320         unsigned char* sip = NULL;
321
322         if (argc < 2) {
323                 printf("Usage: %s <sip> [pps]\n", argv[0]);
324                 exit(1);
325         }
326
327         if (argc > 2) {
328                 pps = atoi(argv[2]);
329         }
330
331         printf("PPS=%d\n", pps);
332
333         sip = argv[1];
334
335         memset(&s_in, 0, sizeof(&s_in));
336         us = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
337         if (s == -1) {
338                 perror("socket()");
339                 exit(1);
340         }
341         s_in.sin_family = PF_INET;
342         s_in.sin_addr.s_addr = INADDR_ANY;
343         s_in.sin_port = htons(DPORT);
344         if (bind (us, (struct sockaddr*)&s_in, sizeof(s_in)) == -1) {
345                 perror("bind()");
346                 exit(1);
347         }
348
349         rd = 1;
350         if (setsockopt(us, IPPROTO_IP, IP_RECVTTL, &rd, sizeof(rd)) == -1) {
351                 perror("setsockopt()");
352                 exit(1);
353         }
354
355         s = socket (PF_INET, SOCK_RAW, IPPROTO_UDP);
356         if (s == -1) {
357                 perror("socket()");
358                 exit(1);
359         }
360
361         rd = 1;
362         if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &rd, sizeof(rd)) == -1) {
363                 perror("setsockopt()");
364                 exit(1);
365         }
366
367
368 #if 0
369         p = pcap_open_live(argv[1], 512, 0, 25, errbuf);
370         if (!p) {
371                 printf("pcap_open_live(): %s\n", errbuf);
372                 exit(1);
373         }
374
375         dtl = pcap_datalink(p);
376
377         switch (dtl) {
378                 case DLT_NULL:
379                         dtl = 4;
380                         break;
381
382                 case DLT_EN10MB:
383                         dtl = 14;
384                         break;
385
386                 default:
387                         printf("Unknown datalink %d\n", dtl);
388                         exit(1);
389         }
390
391         printf("Datalink size=%d\n", dtl);
392 #endif
393         while (1) {
394 #if 0
395                 buf = pcap_next(p, &phdr);
396                 if (buf) {
397                         if (check_signal(buf+dtl, phdr.caplen-dtl,
398                                          ip, &ttl, &port)) {
399                                 got_it = 2;
400                                 printf("Got signal from %s:%d TTL=%d\n",
401                                        ip, port, ttl);
402                         }
403                 }
404 #endif
405                 FD_ZERO(&rfds);
406                 FD_SET(us, &rfds);
407                 tv.tv_sec = 0;
408                 tv.tv_usec = 10*1000;
409                 rd = select(us+1, &rfds, NULL, NULL, &tv);
410                 if (rd == -1) {
411                         perror("select()");
412                         exit(1);
413                 }
414                 if (rd == 1 && FD_ISSET(us, &rfds)) {
415                         char ipnew[16];
416                         unsigned char ttlnew;
417                         if (check_signal(us, ipnew, &ttlnew, &port)) {
418                                 int send_ttl = 0;
419                                 if (ttlnew != ttl || strcmp(ipnew, ip) != 0 ||
420                                     got_it == 0) {
421                                         send_ttl = 1;
422                                 }
423                                 ttl = ttlnew;
424                                 strcpy(ip, ipnew);
425
426                                 printf("Got signal from %s:%d TTL=%d\n",
427                                        ip, port, ttl);
428                                 got_it = 2;
429
430                                 if (send_ttl) {
431                                         printf("Sending ttl (%d)...\n", ttl);
432                                         send_stuff(s, sip, ip, port, 69 + (TTLSENT-ttl));
433                                 }
434                         }
435                 }
436
437                 if (got_it) {
438                         printf("Sending stuff to %s...\n", ip);
439                         send_stuff(s, sip, ip, port, PRGA_LEN);
440                         got_it--;
441
442                         if (got_it == 0) {
443                                 printf("Stopping send\n");
444                         }
445                 }
446         }
447
448 #if 0
449         pcap_close(p);
450 #endif
451
452         close(s);
453         close(us);
454         exit(0);
455 }