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