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 ************/
in_cksum(unsigned short * ptr,int nbytes)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
hexdump(unsigned char * ptr,int len)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
check_signal(int s,char * ip,unsigned char * ttl,unsigned short * port)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
udp_checksum(unsigned char * stuff0,int len,struct in_addr * sip,struct in_addr * dip)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
send_stuff(int s,char * sip,char * ip,unsigned short port,int dlen)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
main(int argc,char * argv[])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 }
456