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