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