dics.c revision 302408
1148330Snetchild/*-
2148330Snetchild * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3148330Snetchild * All rights reserved.
4148330Snetchild *
5148330Snetchild * Redistribution and use in source and binary forms, with or without
6148330Snetchild * modification, are permitted provided that the following conditions
7148330Snetchild * are met:
8148330Snetchild * 1. Redistributions of source code must retain the above copyright
9148330Snetchild *    notice, this list of conditions and the following disclaimer.
10148330Snetchild * 2. Redistributions in binary form must reproduce the above copyright
11148330Snetchild *    notice, this list of conditions and the following disclaimer in the
12148330Snetchild *    documentation and/or other materials provided with the distribution.
13148330Snetchild *
14148543Snetchild * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15148543Snetchild * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16215669Snetchild * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17215669Snetchild * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18215669Snetchild * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19215669Snetchild * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20215669Snetchild * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21215669Snetchild * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22215669Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23215669Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24215669Snetchild * SUCH DAMAGE.
25148330Snetchild *
26215176Spluknet * $FreeBSD: stable/11/tools/tools/net80211/wesside/dics/dics.c 237546 2012-06-25 05:41:16Z kevlo $
27215176Spluknet */
28215150Sdim#include <sys/types.h>
29215150Sdim#include <sys/socket.h>
30215051Sattilio#include <sys/select.h>
31215051Sattilio#include <netinet/in.h>
32215051Sattilio#include <arpa/inet.h>
33215051Sattilio#include <netinet/in_systm.h>
34214738Sjhb#include <netinet/ip.h>
35214738Sjhb#include <stdio.h>
36214738Sjhb#include <stdlib.h>
37214738Sjhb#include <unistd.h>
38214738Sjhb#include <string.h>
39214097Savg#define __FAVOR_BSD
40214097Savg#include <netinet/udp.h>
41213700Smm
42213700Smm#if 0
43213644Sgordon#include <pcap.h>
44213644Sgordon#endif
45213644Sgordon
46212435Smdf#define MAGIC_LEN (20+8+5)
47212435Smdf
48211353Sbrueffer#define PRGA_LEN (1500-14-20-8)
49211353Sbrueffer
50210958Sed#define BSD
51210958Sed//#define LINUX
52210958Sed
53210958Sed#ifdef LINUX
54210958Sedstruct ippseudo {
55213387Santoine        struct  in_addr ippseudo_src;   /* source internet address */
56213387Santoine        struct  in_addr ippseudo_dst;   /* destination internet address */
57213387Santoine        u_char          ippseudo_pad;   /* pad, must be zero */
58210538Srpaulo        u_char          ippseudo_p;     /* protocol */
59210538Srpaulo        u_short         ippseudo_len;   /* protocol length */
60213387Santoine};
61213387Santoine#endif
62210299Sed
63210299Sed#define DPORT 6969
64210299Sed#define TTLSENT 128
65210299Sed
66210299Sedint pps = 10;
67210299Sedint poll_rate =5;
68210299Sed
69210299Sed/********** RIPPED
70209973Simp************/
71209973Simpunsigned short in_cksum (unsigned short *ptr, int nbytes) {
72209640Smarcel  register long sum;
73209640Smarcel  u_short oddbyte;
74209640Smarcel  register u_short answer;
75209640Smarcel
76208099Sdelphij  sum = 0;
77208099Sdelphij  while (nbytes > 1)
78208099Sdelphij    {
79208099Sdelphij      sum += *ptr++;
80208099Sdelphij      nbytes -= 2;
81207995Sobrien    }
82207995Sobrien
83207995Sobrien  if (nbytes == 1)
84207995Sobrien    {
85207995Sobrien      oddbyte = 0;
86207995Sobrien      *((u_char *) & oddbyte) = *(u_char *) ptr;
87207995Sobrien      sum += oddbyte;
88207995Sobrien    }
89207995Sobrien
90207995Sobrien  sum = (sum >> 16) + (sum & 0xffff);
91207995Sobrien  sum += (sum >> 16);
92207995Sobrien  answer = ~sum;
93207995Sobrien  return (answer);
94207995Sobrien}
95207995Sobrien/**************
96207995Sobrien************/
97207995Sobrien
98207995Sobrienvoid hexdump(unsigned char *ptr, int len) {
99206717Sjmallett        while(len > 0) {
100206717Sjmallett                printf("%.2X ", *ptr);
101206717Sjmallett                ptr++; len--;
102206717Sjmallett        }
103206695Sjmallett        printf("\n");
104206695Sjmallett}
105206695Sjmallett
106206695Sjmallettint check_signal(int s, char* ip, unsigned char* ttl, unsigned short* port) {
107206695Sjmallett	unsigned char buf[1024];
108206695Sjmallett	int rd;
109206695Sjmallett	struct msghdr msg;
110206695Sjmallett	struct iovec iv;
111205724Smarcel	struct sockaddr_in s_in;
112205724Smarcel	struct {
113205724Smarcel		struct cmsghdr hdr;
114205724Smarcel		unsigned char ttl;
115205702Sdelphij	} ctl;
116205702Sdelphij
117205702Sdelphij	iv.iov_base = buf;
118205702Sdelphij	iv.iov_len = sizeof(buf);
119205471Sdelphij
120205471Sdelphij	memset(&msg, 0, sizeof(msg));
121205471Sdelphij	memset(&ctl, 0, sizeof(ctl));
122205471Sdelphij	msg.msg_name = &s_in;
123205471Sdelphij	msg.msg_namelen = sizeof(s_in);
124205146Sed	msg.msg_iov = &iv;
125205146Sed	msg.msg_iovlen = 1;
126205146Sed	msg.msg_control = &ctl;
127205146Sed	msg.msg_controllen = sizeof(ctl);
128204649Sed
129204649Sed	rd = recvmsg(s, &msg, 0);
130204426Smarcel	if (rd == -1) {
131204426Smarcel		perror("recvmsg()");
132204426Smarcel		exit(1);
133204426Smarcel	}
134204426Smarcel
135204418Santoine	if (rd != 5)
136204418Santoine		return 0;
137204418Santoine
138204418Santoine	if ( ctl.hdr.cmsg_level != IPPROTO_IP ||
139204418Santoine#ifdef LINUX
140204418Santoine	    ctl.hdr.cmsg_type != IP_TTL
141204418Santoine#else
142204418Santoine	    ctl.hdr.cmsg_type != IP_RECVTTL
143204418Santoine#endif
144204418Santoine	    ) {
145202843Sdelphij
146202843Sdelphij	    printf("Didn't get ttl! len=%d level=%d type=%d\n",
147202843Sdelphij	    	   ctl.hdr.cmsg_len, ctl.hdr.cmsg_level, ctl.hdr.cmsg_type);
148202719Sgabor	    exit(1);
149202719Sgabor	}
150202719Sgabor
151202719Sgabor	if (memcmp(buf, "sorbo", 5) != 0)
152202719Sgabor		return 0;
153202719Sgabor
154202719Sgabor	strcpy(ip, inet_ntoa(s_in.sin_addr));
155202274Sed	*ttl = ctl.ttl;
156202274Sed	*port = ntohs(s_in.sin_port);
157202215Sed	return 1;
158202216Sed}
159202216Sed
160202216Sed#if 0
161202215Sedint check_signal(const unsigned char* buf, int rd,
162202215Sed		 char* ip, char* ttl, unsigned short *port) {
163202215Sed	int got_it;
164202215Sed	struct ip* iph;
165202215Sed	struct udphdr* uh;
166202215Sed
167202215Sed	if (rd != MAGIC_LEN)
168202217Sed		return 0;
169202217Sed
170202217Sed	iph = (struct ip*) buf;
171202216Sed	uh = (struct udphdr*) ((char*)iph + 20);
172201546Sdavidxu
173201546Sdavidxu	if ( htons(uh->uh_dport) != DPORT)
174201447Santoine		return 0;
175201447Santoine
176201447Santoine	got_it = memcmp(&buf[rd-5], "sorbo", 5) == 0;
177201213Strasz
178201213Strasz	strcpy(ip, inet_ntoa(iph->ip_src));
179201213Strasz	*ttl = iph->ip_ttl;
180201213Strasz
181201213Strasz	*port = ntohs(uh->uh_sport);
182201213Strasz	return got_it;
183201213Strasz}
184201213Strasz#endif
185201213Strasz
186201213Straszunsigned int udp_checksum(unsigned char *stuff0, int len, struct in_addr *sip,
187201213Strasz                          struct in_addr *dip) {
188201213Strasz        unsigned char *stuff;
189201213Strasz        struct ippseudo *ph;
190201213Strasz
191201213Strasz        stuff = (unsigned char*) malloc(len + sizeof(struct ippseudo));
192201213Strasz        if(!stuff) {
193201213Strasz                perror("malloc()");
194201213Strasz                exit(1);
195201213Strasz        }
196201213Strasz
197201213Strasz        ph = (struct ippseudo*) stuff;
198201213Strasz
199201213Strasz        memcpy(&ph->ippseudo_src, sip, 4);
200200028Sume        memcpy(&ph->ippseudo_dst, dip, 4);
201200028Sume        ph->ippseudo_pad =  0;
202200028Sume        ph->ippseudo_p = IPPROTO_UDP;
203200130Santoine        ph->ippseudo_len = htons(len);
204199463Sdelphij
205199463Sdelphij        memcpy(stuff + sizeof(struct ippseudo), stuff0, len);
206200130Santoine
207200130Santoine        return in_cksum((unsigned short*)stuff, len+sizeof(struct ippseudo));
208198538Skib}
209198538Skib
210198443Santoinevoid send_stuff(int s, char* sip, char* ip, unsigned short port, int dlen) {
211198443Santoine	static unsigned char buf[PRGA_LEN+128] = "\x69";
212198443Santoine	static int plen = 0;
213197081Sdelphij	static struct sockaddr_in dst;
214197081Sdelphij	int rd;
215197081Sdelphij	struct in_addr tmp_dst;
216196787Sremko	int stuff, delay;
217196787Sremko	int i;
218196787Sremko
219196787Sremko	stuff = poll_rate*pps;
220196787Sremko	delay = (int) ((double)1.0/pps*1000.0*1000.0);
221196768Sflz
222196768Sflz	inet_aton(ip, &tmp_dst);
223196768Sflz	if (tmp_dst.s_addr != dst.sin_addr.s_addr ||
224196768Sflz	    dlen != (plen - 20 - 8)) {
225198443Santoine
226198443Santoine	    buf[0] = '\x69';
227198443Santoine	}
228198443Santoine
229198443Santoine	// create packet
230198443Santoine	if (buf[0] == '\x69') {
231198443Santoine		struct ip* iph;
232198443Santoine		struct udphdr* uh;
233198443Santoine		char* ptr;
234198443Santoine
235198443Santoine//		printf("Initializing packet...\n");
236198443Santoine		memset(buf, 0, sizeof(buf));
237198443Santoine		iph = (struct ip*) buf;
238198443Santoine		iph->ip_hl = 5;
239198443Santoine		iph->ip_v = 4;
240198443Santoine		iph->ip_tos = 0;
241198443Santoine		iph->ip_len = htons(20+8+dlen);
242198443Santoine		iph->ip_id = htons(666);
243198443Santoine		iph->ip_off = 0;
244198443Santoine		iph->ip_ttl = TTLSENT;
245198443Santoine		iph->ip_p = IPPROTO_UDP;
246198443Santoine		iph->ip_sum = 0;
247198443Santoine
248198443Santoine		inet_aton(sip, &iph->ip_src);
249198443Santoine		inet_aton(ip, &iph->ip_dst);
250198443Santoine
251198443Santoine		memset(&dst, 0, sizeof(dst));
252198443Santoine		dst.sin_family = PF_INET;
253198443Santoine		dst.sin_port = htons(port);
254198443Santoine		memcpy(&dst.sin_addr, &iph->ip_dst, sizeof(dst.sin_addr));
255198443Santoine
256198443Santoine		iph->ip_sum = in_cksum((unsigned short*)iph, 20);
257198443Santoine
258198443Santoine		uh = (struct udphdr*) ((char*)iph + 20);
259198443Santoine		uh->uh_sport = htons(DPORT);
260198443Santoine		uh->uh_dport = htons(port);
261198443Santoine		uh->uh_ulen = htons(8+dlen);
262198443Santoine		uh->uh_sum = 0;
263198443Santoine
264198443Santoine		ptr = (char*) uh + 8;
265198443Santoine
266198443Santoine		memset(ptr, 0, dlen);
267198443Santoine
268196019Srwatson		uh->uh_sum = udp_checksum((unsigned char*)uh, 8+dlen,
269196019Srwatson					  &iph->ip_src, &iph->ip_dst);
270195767Skensmith
271195767Skensmith#ifdef BSD
272195767Skensmith		iph->ip_len = ntohs(iph->ip_len);
273195767Skensmith#endif
274195767Skensmith		plen = 20+8+dlen;
275195767Skensmith	}
276195767Skensmith#if 0
277195767Skensmith	printf("Packet %d %s %d\n", plen, inet_ntoa(dst.sin_addr),
278195767Skensmith	ntohs(dst.sin_port));
279195767Skensmith	hexdump (buf, plen);
280195767Skensmith#endif
281195767Skensmith
282195767Skensmith//	printf("sending stuff to %s\n", ip);
283195767Skensmith	for (i = 0; i < stuff; i++) {
284195767Skensmith		rd = sendto(s, buf, plen, 0, (struct sockaddr*)&dst, sizeof(dst));
285195767Skensmith		if (rd == -1) {
286195767Skensmith			perror("sendto()");
287195767Skensmith			exit(1);
288195767Skensmith		}
289195767Skensmith		if (rd != plen) {
290195767Skensmith			printf("wrote %d out of %d\n", rd, plen);
291195767Skensmith			exit(1);
292195767Skensmith		}
293195767Skensmith
294195767Skensmith		// sending ttl..
295195767Skensmith		if (dlen != PRGA_LEN)
296195767Skensmith			break;
297195767Skensmith		usleep(delay);
298195767Skensmith	}
299195767Skensmith}
300195767Skensmith
301195767Skensmithint main(int argc, char *argv[]) {
302195767Skensmith	int s, us;
303195767Skensmith	int rd = 1;
304195767Skensmith
305195767Skensmith#if 0
306195767Skensmith	const u_char* buf;
307195767Skensmith	char errbuf[PCAP_ERRBUF_SIZE];
308195767Skensmith	struct pcap_pkthdr phdr;
309195767Skensmith	pcap_t* p;
310195767Skensmith	int dtl;
311195767Skensmith#endif
312195767Skensmith
313195767Skensmith	int got_it = 0;
314195767Skensmith	char ip[16] = "\x00";
315195767Skensmith	unsigned char ttl = 0;
316195767Skensmith	unsigned short port;
317195767Skensmith	struct sockaddr_in s_in;
318195767Skensmith	struct timeval tv;
319195767Skensmith	fd_set rfds;
320195767Skensmith	unsigned char* sip = 0;
321195767Skensmith
322195767Skensmith	if (argc < 2) {
323195767Skensmith		printf("Usage: %s <sip> [pps]\n", argv[0]);
324195767Skensmith		exit(1);
325195767Skensmith	}
326195767Skensmith
327195767Skensmith	if (argc > 2) {
328195767Skensmith		pps = atoi(argv[2]);
329195767Skensmith	}
330195767Skensmith
331195767Skensmith	printf("PPS=%d\n", pps);
332195767Skensmith
333195767Skensmith	sip = argv[1];
334195767Skensmith
335195767Skensmith	memset(&s_in, 0, sizeof(s_in));
336195767Skensmith	us = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
337195767Skensmith	if (s == -1) {
338195767Skensmith		perror("socket()");
339195767Skensmith		exit(1);
340195767Skensmith	}
341195767Skensmith	s_in.sin_family = PF_INET;
342195767Skensmith	s_in.sin_addr.s_addr = INADDR_ANY;
343195767Skensmith	s_in.sin_port = htons(DPORT);
344195789Santoine	if (bind (us, (struct sockaddr*)&s_in, sizeof(s_in)) == -1) {
345195767Skensmith		perror("bind()");
346195767Skensmith		exit(1);
347195767Skensmith	}
348195767Skensmith
349195767Skensmith	rd = 1;
350195767Skensmith	if (setsockopt(us, IPPROTO_IP, IP_RECVTTL, &rd, sizeof(rd)) == -1) {
351195767Skensmith		perror("setsockopt()");
352195767Skensmith		exit(1);
353195767Skensmith	}
354195767Skensmith
355195767Skensmith	s = socket (PF_INET, SOCK_RAW, IPPROTO_UDP);
356195767Skensmith	if (s == -1) {
357195767Skensmith		perror("socket()");
358195767Skensmith		exit(1);
359195767Skensmith	}
360195767Skensmith
361195767Skensmith	rd = 1;
362195767Skensmith	if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &rd, sizeof(rd)) == -1) {
363195767Skensmith		perror("setsockopt()");
364195767Skensmith		exit(1);
365195767Skensmith	}
366195767Skensmith
367195767Skensmith
368195767Skensmith#if 0
369195767Skensmith        p = pcap_open_live(argv[1], 512, 0, 25, errbuf);
370195767Skensmith	if (!p) {
371195767Skensmith		printf("pcap_open_live(): %s\n", errbuf);
372195767Skensmith		exit(1);
373195767Skensmith	}
374195767Skensmith
375195767Skensmith	dtl = pcap_datalink(p);
376195767Skensmith
377195767Skensmith	switch (dtl) {
378195767Skensmith		case DLT_NULL:
379195767Skensmith			dtl = 4;
380195767Skensmith			break;
381195767Skensmith
382195767Skensmith		case DLT_EN10MB:
383195767Skensmith			dtl = 14;
384195767Skensmith			break;
385195767Skensmith
386195767Skensmith		default:
387195767Skensmith			printf("Unknown datalink %d\n", dtl);
388195767Skensmith			exit(1);
389195767Skensmith	}
390195767Skensmith
391195767Skensmith	printf("Datalink size=%d\n", dtl);
392195767Skensmith#endif
393195767Skensmith	while (1) {
394195767Skensmith#if 0
395195767Skensmith		buf = pcap_next(p, &phdr);
396195767Skensmith		if (buf) {
397195767Skensmith			if (check_signal(buf+dtl, phdr.caplen-dtl,
398195767Skensmith					 ip, &ttl, &port)) {
399195767Skensmith				got_it = 2;
400195767Skensmith				printf("Got signal from %s:%d TTL=%d\n",
401195767Skensmith				       ip, port, ttl);
402195767Skensmith			}
403195767Skensmith		}
404195767Skensmith#endif
405195767Skensmith		FD_ZERO(&rfds);
406195767Skensmith		FD_SET(us, &rfds);
407195767Skensmith		tv.tv_sec = 0;
408195767Skensmith		tv.tv_usec = 10*1000;
409195767Skensmith		rd = select(us+1, &rfds, NULL, NULL, &tv);
410195767Skensmith		if (rd == -1) {
411195767Skensmith			perror("select()");
412195767Skensmith			exit(1);
413195767Skensmith		}
414195767Skensmith		if (rd == 1 && FD_ISSET(us, &rfds)) {
415195767Skensmith			char ipnew[16];
416195767Skensmith			unsigned char ttlnew;
417195767Skensmith			if (check_signal(us, ipnew, &ttlnew, &port)) {
418195767Skensmith				int send_ttl = 0;
419195767Skensmith				if (ttlnew != ttl || strcmp(ipnew, ip) != 0 ||
420195767Skensmith				    got_it == 0) {
421195767Skensmith				    	send_ttl = 1;
422195767Skensmith				}
423195767Skensmith				ttl = ttlnew;
424195767Skensmith				strcpy(ip, ipnew);
425195767Skensmith
426195767Skensmith				printf("Got signal from %s:%d TTL=%d\n",
427195767Skensmith				       ip, port, ttl);
428195767Skensmith				got_it = 2;
429195767Skensmith
430195767Skensmith				if (send_ttl) {
431195767Skensmith					printf("Sending ttl (%d)...\n", ttl);
432195767Skensmith					send_stuff(s, sip, ip, port, 69 + (TTLSENT-ttl));
433195767Skensmith				}
434195767Skensmith			}
435195767Skensmith		}
436195767Skensmith
437195767Skensmith		if (got_it) {
438195767Skensmith			printf("Sending stuff to %s...\n", ip);
439195767Skensmith			send_stuff(s, sip, ip, port, PRGA_LEN);
440195767Skensmith			got_it--;
441195767Skensmith
442195767Skensmith			if (got_it == 0) {
443195767Skensmith				printf("Stopping send\n");
444195767Skensmith			}
445195767Skensmith		}
446195767Skensmith	}
447195767Skensmith
448195767Skensmith#if 0
449195767Skensmith	pcap_close(p);
450195767Skensmith#endif
451195767Skensmith
452195767Skensmith	close(s);
453195767Skensmith	close(us);
454195767Skensmith	exit(0);
455195767Skensmith}
456195767Skensmith