#define GOALRATE 45000 #define RTIMEOUT 30 #define WTIMEOUT 10 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct ip_hdr_t { #if (BYTE_ORDER == LITTLE_ENDIAN) uint8_t ip_hl:4, ip_v:4; #elif (BYTE_ORDER == BIG_ENDIAN) uint8_t ip_v:4, ip_hl:4; #else #error "Adjust your defines" #endif uint8_t ip_tos; uint16_t ip_len; uint16_t ip_id; uint16_t ip_off; uint8_t ip_ttl; uint8_t ip_p; uint16_t ip_sum; uint32_t ip_src; uint32_t ip_dst; }__attribute__((packed)); struct tcp_hdr_t { uint16_t tcp_sport; uint16_t tcp_dport; uint32_t tcp_seq; uint32_t tcp_ackseq; #if (BYTE_ORDER == LITTLE_ENDIAN) uint8_t res:4, doff:4; #elif (BYTE_ORDER == BIG_ENDIAN) uint8_t doff:4, res:4; #else #error "Adjust your defines" #endif uint8_t tcp_flags; uint16_t tcp_window; uint16_t tcp_sum; uint16_t tcp_urgptr; } __attribute__((packed)); struct pseudo_hdr_t { uint32_t src; uint32_t dst; uint8_t pad; uint8_t proto; uint16_t tcpl; struct tcp_hdr_t tcp; }__attribute__((packed)); struct net { uint32_t start; uint32_t stop; uint32_t count; uint32_t pos; uint32_t xor; struct net *next; uint32_t bitmap[0]; }; struct pkt { struct ip_hdr_t ip; struct tcp_hdr_t tcp; }; #define HSIZE 512 struct net *netlist = NULL; int check_map(uint32_t ip) { struct net *net; for (net = netlist; net; net=net->next) { //printf("chknet %x %x %x\n", net->start, ip, net->stop); if ((ip < net->start) || (ip > net->stop)) continue; int pos = (ip-net->start); if ((net->bitmap[pos/32] && (1<<(pos%32)))==0) { //printf("process %x\n", ip); net->bitmap[pos/32] |= (1<<(pos%32)); return 1; } } return 0; } uint32_t getaddr(char *s) { union { struct in_addr ia; in_addr_t iat; uint32_t i; } a; a.iat = inet_addr(s); return ntohl(a.i); } uint16_t net_ip_sum (const uint16_t *ptr, int len) { register int sum = 0; while (len > 1) { sum += *ptr++; len -= 2; } if (len == 1) sum += *((unsigned char *) ptr); sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return (~sum); } #define SNAPLEN 128*1024 struct pseudo_hdr_t pseudo; struct pkt p; void init_pkt(uint32_t srcip, int dport) { p.ip.ip_src = htonl(srcip); pseudo.src = p.ip.ip_src; pseudo.pad = 0; pseudo.proto = IPPROTO_TCP; pseudo.tcpl = htons(sizeof p.tcp); p.ip.ip_v = 4; p.ip.ip_hl = 5; p.ip.ip_tos = 0; p.ip.ip_len = sizeof(p); p.ip.ip_off = 0; p.ip.ip_id = 0x1337; p.ip.ip_ttl = 63; p.ip.ip_p = IPPROTO_TCP; p.tcp.tcp_sport = htons(1337); p.tcp.tcp_dport = htons(dport); p.tcp.tcp_seq = 0xdeadbabe; p.tcp.tcp_ackseq = 0xcafebeef; p.tcp.doff = sizeof(p.tcp)/4; p.tcp.tcp_flags = 0x2; // SYN p.tcp.tcp_window = 100; p.tcp.tcp_urgptr = 0; } void send_pkt(int sock, uint32_t dstip) { static struct sockaddr_in sin; p.ip.ip_dst = htonl(dstip); p.ip.ip_sum = net_ip_sum((void*)&p.ip, sizeof p.ip); pseudo.dst = p.ip.ip_dst; p.tcp.tcp_sum = 0; memcpy(&pseudo.tcp, &p.tcp, sizeof p.tcp); p.tcp.tcp_sum = net_ip_sum((void*)&pseudo, sizeof pseudo); sin.sin_family = AF_INET; sin.sin_port = p.tcp.tcp_dport; memcpy(&sin.sin_addr.s_addr,&p.ip.ip_dst,4); sendto(sock, &p, sizeof(p),0, (struct sockaddr *) &sin, sizeof(sin)); } struct pollfd *pollfds = NULL; int *tmap = NULL; int npoll = 0; int inflight=0; time_t oldnow; time_t now; void poll_add(int fd, int events) { int i; for (i = 0; i < npoll; i++) { if (pollfds[i].fd == -1) break; } if (i == npoll) { pollfds = realloc(pollfds, sizeof(pollfds[0])*(++npoll)); tmap = realloc(tmap, sizeof(int)*(npoll)); } //printf("adding @ idx %d fd %d\n", i, fd); pollfds[i].fd = fd; pollfds[i].events = events; tmap[i] = now; inflight++; } void poll_del(int idx) { //printf("deleting idx %d, fd %d\n", idx, pollfds[idx].fd); assert(pollfds[idx].fd != -1); pollfds[idx].fd = -1; pollfds[idx].events = 0; inflight--; } int main(int argc, char *argv[]) { char buf[512]; int done; int dport; double probed; double total; double goal; double found; double rate; double irate; FILE *f; int sock; struct sockaddr_in sin; memset(&sin, 0,sizeof sin); char pcap_err[PCAP_ERRBUF_SIZE]; pcap_t *pc; int pc_off = 0; struct bpf_program filter; struct pcap_pkthdr ph; int pfd; FILE *fout; double penalty; int i; struct net *net; unsigned char *gotpk; struct pkt *rpkt; int finishers = 0; int repeats=0; double limit; int pks; signal(SIGPIPE, SIG_IGN); /* srcip srcif dstport srclist dstlist * 1 2 3 4 5 * */ assert(argc==6 && "srcip srcif dstport srclist dstlist"); assert((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))>=0); assert(f = fopen(argv[4], "r")); assert(fout = fopen(argv[5], "a")); dport = strtol(argv[3], NULL, 10); pc = pcap_open_live(argv[2], sizeof(struct pkt) + 32, 0, 100, pcap_err); // pcap_setnonblock(pc, 1, pcap_err); if (pcap_datalink(pc) == DLT_EN10MB) pc_off = 14; assert(pcap_compile(pc, &filter, "(ip proto \\tcp) and ((tcp[13] & (tcp-ack+tcp-rst)) = tcp-ack) and dst port 1337", 0, 0) != -1); assert(pcap_setfilter(pc, &filter) != -1); poll_add(pfd=pcap_fileno(pc), POLLIN); uint32_t sip = getaddr(argv[1]); init_pkt(sip, dport); probed=irate = rate = found = total = goal = 0; limit = 1000; pks = 0; while (fgets(buf,512,f)) { struct net *net; char a[512]; char b[512]; uint32_t na,nb,l; assert(sscanf(buf,"%[^-]-%s",a,b)==2); na = getaddr(a); nb = getaddr(b); l = sizeof *net + ((nb-na+32)/32)*sizeof(uint32_t); net = malloc(l); memset(net,0,l); net->start = na; net->stop = nb; net->count = nb-na+1; goal+= net->count; //printf("%.2f\n", goal); net->next = netlist; net->pos = 0; srand(time(NULL)); net->xor = rand() % net->count; netlist = net; } net = NULL; fprintf(stderr, "scanning %.2fM IPs for port %d\n", goal/1000000, dport); while (1) { int igots=0; pks=0; while (pksnext) { if (pks>limit) break; if (net->pos == net->count) continue; send_pkt(sock, net->start + ((net->pos)) % net->count); rate++; net->pos++; total++; pks++; } } now = time(NULL); usleep(2); if (now > oldnow+3) { rate = rate/(now-oldnow); irate = irate/(now-oldnow); limit /= rate/GOALRATE; if (limit<1) limit=1; if (limit>10000) limit=10000; fprintf(stderr, "txrate %.2fKpps (limit %.2fKpp/burst) || rxrate %.2fpps || %.2f %% done (%.2fM) || %.0f probed (%.2f prevalency)\r", rate/1000, limit/1000, irate, total*100/goal, total/1000000, probed, probed * 100 / goal); rate=0; irate=0; oldnow = now; if (total==goal) { fprintf(stderr,"Finished!\n"); if (finishers++>30) break; } } } fprintf(stderr, "\n"); }