dics.c revision 161030
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: head/tools/tools/net80211/wesside/dics/dics.c 161030 2006-08-07 00:05:04Z sam $ 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 54struct 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 66int pps = 10; 67int poll_rate =5; 68 69/********** RIPPED 70************/ 71unsigned 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 98void hexdump(unsigned char *ptr, int len) { 99 while(len > 0) { 100 printf("%.2X ", *ptr); 101 ptr++; len--; 102 } 103 printf("\n"); 104} 105 106int 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 161int 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 186unsigned 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 210void 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 301int 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 = 0; 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