2 * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
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>
40 #include <netinet/udp.h>
46 #define MAGIC_LEN (20+8+5)
48 #define PRGA_LEN (1500-14-20-8)
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 */
71 unsigned short in_cksum (unsigned short *ptr, int nbytes) {
74 register u_short answer;
86 *((u_char *) & oddbyte) = *(u_char *) ptr;
90 sum = (sum >> 16) + (sum & 0xffff);
98 void hexdump(unsigned char *ptr, int len) {
100 printf("%.2X ", *ptr);
106 int check_signal(int s, char* ip, unsigned char* ttl, unsigned short* port) {
107 unsigned char buf[1024];
111 struct sockaddr_in s_in;
118 iv.iov_len = sizeof(buf);
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);
126 msg.msg_control = &ctl;
127 msg.msg_controllen = sizeof(ctl);
129 rd = recvmsg(s, &msg, 0);
138 if ( ctl.hdr.cmsg_level != IPPROTO_IP ||
140 ctl.hdr.cmsg_type != IP_TTL
142 ctl.hdr.cmsg_type != IP_RECVTTL
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);
151 if (memcmp(buf, "sorbo", 5) != 0)
154 strcpy(ip, inet_ntoa(s_in.sin_addr));
156 *port = ntohs(s_in.sin_port);
161 int check_signal(const unsigned char* buf, int rd,
162 char* ip, char* ttl, unsigned short *port) {
170 iph = (struct ip*) buf;
171 uh = (struct udphdr*) ((char*)iph + 20);
173 if ( htons(uh->uh_dport) != DPORT)
176 got_it = memcmp(&buf[rd-5], "sorbo", 5) == 0;
178 strcpy(ip, inet_ntoa(iph->ip_src));
181 *port = ntohs(uh->uh_sport);
186 unsigned int udp_checksum(unsigned char *stuff0, int len, struct in_addr *sip,
187 struct in_addr *dip) {
188 unsigned char *stuff;
191 stuff = (unsigned char*) malloc(len + sizeof(struct ippseudo));
197 ph = (struct ippseudo*) stuff;
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);
205 memcpy(stuff + sizeof(struct ippseudo), stuff0, len);
207 return in_cksum((unsigned short*)stuff, len+sizeof(struct ippseudo));
210 void send_stuff(int s, char* sip, char* ip, unsigned short port, int dlen) {
211 static unsigned char buf[PRGA_LEN+128] = "\x69";
213 static struct sockaddr_in dst;
215 struct in_addr tmp_dst;
219 stuff = poll_rate*pps;
220 delay = (int) ((double)1.0/pps*1000.0*1000.0);
222 inet_aton(ip, &tmp_dst);
223 if (tmp_dst.s_addr != dst.sin_addr.s_addr ||
224 dlen != (plen - 20 - 8)) {
230 if (buf[0] == '\x69') {
235 // printf("Initializing packet...\n");
236 memset(buf, 0, sizeof(buf));
237 iph = (struct ip*) buf;
241 iph->ip_len = htons(20+8+dlen);
242 iph->ip_id = htons(666);
244 iph->ip_ttl = TTLSENT;
245 iph->ip_p = IPPROTO_UDP;
248 inet_aton(sip, &iph->ip_src);
249 inet_aton(ip, &iph->ip_dst);
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));
256 iph->ip_sum = in_cksum((unsigned short*)iph, 20);
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);
264 ptr = (char*) uh + 8;
266 memset(ptr, 0, dlen);
268 uh->uh_sum = udp_checksum((unsigned char*)uh, 8+dlen,
269 &iph->ip_src, &iph->ip_dst);
272 iph->ip_len = ntohs(iph->ip_len);
277 printf("Packet %d %s %d\n", plen, inet_ntoa(dst.sin_addr),
278 ntohs(dst.sin_port));
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));
290 printf("wrote %d out of %d\n", rd, plen);
295 if (dlen != PRGA_LEN)
301 int main(int argc, char *argv[]) {
307 char errbuf[PCAP_ERRBUF_SIZE];
308 struct pcap_pkthdr phdr;
314 char ip[16] = "\x00";
315 unsigned char ttl = 0;
317 struct sockaddr_in s_in;
320 unsigned char* sip = 0;
323 printf("Usage: %s <sip> [pps]\n", argv[0]);
331 printf("PPS=%d\n", pps);
335 memset(&s_in, 0, sizeof(s_in));
336 us = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
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) {
350 if (setsockopt(us, IPPROTO_IP, IP_RECVTTL, &rd, sizeof(rd)) == -1) {
351 perror("setsockopt()");
355 s = socket (PF_INET, SOCK_RAW, IPPROTO_UDP);
362 if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &rd, sizeof(rd)) == -1) {
363 perror("setsockopt()");
369 p = pcap_open_live(argv[1], 512, 0, 25, errbuf);
371 printf("pcap_open_live(): %s\n", errbuf);
375 dtl = pcap_datalink(p);
387 printf("Unknown datalink %d\n", dtl);
391 printf("Datalink size=%d\n", dtl);
395 buf = pcap_next(p, &phdr);
397 if (check_signal(buf+dtl, phdr.caplen-dtl,
400 printf("Got signal from %s:%d TTL=%d\n",
408 tv.tv_usec = 10*1000;
409 rd = select(us+1, &rfds, NULL, NULL, &tv);
414 if (rd == 1 && FD_ISSET(us, &rfds)) {
416 unsigned char ttlnew;
417 if (check_signal(us, ipnew, &ttlnew, &port)) {
419 if (ttlnew != ttl || strcmp(ipnew, ip) != 0 ||
426 printf("Got signal from %s:%d TTL=%d\n",
431 printf("Sending ttl (%d)...\n", ttl);
432 send_stuff(s, sip, ip, port, 69 + (TTLSENT-ttl));
438 printf("Sending stuff to %s...\n", ip);
439 send_stuff(s, sip, ip, port, PRGA_LEN);
443 printf("Stopping send\n");