/* * frag * by: Fryxar * e-mail: fryxar@yahoo.com.ar * * Fragment ICMP packet generator */ #include #include #include #include #include #include #include #include #define ERROR(msg) {perror(msg); exit -1;} #define FRAGS_ALL 0 #define FRAGS_ODD 1 #define FRAGS_EVEN 2 int open_packet() { int s, on = 1; if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) ERROR("socket"); if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) ERROR("setsockopt"); return s; } unsigned short in_cksum(unsigned short *addr,int len) { register int sum = 0; u_short answer = 0; register u_short *w = addr; register int nleft = len; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); } int send_packet(int s, struct sockaddr_in saddr, struct sockaddr_in daddr, int protocol, char frags, int id, int frag_len, int tot_len) { unsigned char packet[IP_MAXPACKET]; struct iphdr *iphdr; struct icmphdr *icmphdr; int offset, length; int start, step; switch(frags) { case FRAGS_ALL: start = 0; step = (frag_len<<3); break; case FRAGS_EVEN: start = 0; step = 2*(frag_len<<3); break; case FRAGS_ODD: start = (frag_len<<3); step = 2*(frag_len<<3); break; } memset(packet, 0, IP_MAXPACKET); length = sizeof(struct iphdr) + (frag_len<<3); iphdr = (struct iphdr *)packet; icmphdr = (struct icmphdr *)(packet + sizeof(struct iphdr)); iphdr->ihl = 5; iphdr->version = IPVERSION; iphdr->tot_len = htons(length); iphdr->id = htons(id); iphdr->ttl = IPDEFTTL; iphdr->protocol = protocol; iphdr->saddr = saddr.sin_addr.s_addr; iphdr->daddr = daddr.sin_addr.s_addr; for(offset = start; offset < tot_len; offset += step) { if(offset) { // Not first fragment iphdr->frag_off = htons(offset>>3); bzero(packet + sizeof(struct iphdr), IP_MAXPACKET - sizeof(struct iphdr)); } else { // First fragment iphdr->frag_off = 0; if(protocol == IPPROTO_ICMP) { icmphdr->type = ICMP_ECHO; icmphdr->code = 0; icmphdr->un.echo.id = 0; icmphdr->un.echo.sequence = 0; icmphdr->checksum = (unsigned short)in_cksum((unsigned short *)icmphdr, tot_len); } } if(offset + (frag_len<<3) < tot_len) { iphdr->frag_off |= htons(IP_MF); } else { length = sizeof(struct iphdr) + tot_len - offset; iphdr->tot_len = htons(length); } iphdr->check = (unsigned short)in_cksum((unsigned short *)iphdr, sizeof(struct iphdr)); if(sendto(s, packet, length, 0x0, (struct sockaddr *)&daddr, sizeof(struct sockaddr)) != length) ERROR("sendto"); } } void usage(char *program) { fprintf(stderr, "frag v"VERSION"\n" "usage: %s [options] \n\n" "options:\n" " -i Starting session id (range: 1-65535)\n" " -s Fragments size (x 8)\n" " -l Total packet size\n" " -t Set send policity (odd|even|all)\n" " -p Set protocol (tcp|udp|icmp...)\n" " -a Amount of packet to send\n" "\ndefault:\n" "%s -i 1 -t all -s 7 -p icmp -l 64000 -a 1 my_host.com your_host.com\n" "\n", program, program); exit(-1); } int main(int argc, char *argv[]) { char *shost, *dhost; struct hostent *hostentry; struct sockaddr_in saddr, daddr; struct protoent *protoent; int s, i; int id = 1, size = 7, len = 64000, amount = 1; int protocol = IPPROTO_ICMP, type = FRAGS_ALL; if(argc < 3) usage(argv[0]); while((i = getopt(argc, argv, "a:i:s:l:t:p:")) != -1) { switch(i) { case 'i': if(strlen(optarg) == 0) usage(argv[0]); id = atoi(optarg); break; case 's': if(strlen(optarg) == 0) usage(argv[0]); size = atoi(optarg); break; case 'a': if(strlen(optarg) == 0) usage(argv[0]); amount = atoi(optarg); break; case 'l': if(strlen(optarg) == 0) usage(argv[0]); len = atoi(optarg); break; case 't': if(!memcmp(optarg, "odd", 4)) type = FRAGS_ODD; else if(!memcmp(optarg, "even", 5)) type = FRAGS_EVEN; else if(!memcmp(optarg, "all", 4)) type = FRAGS_ALL; else usage(argv[0]); break; case 'p': if((protoent=getprotobyname(optarg)) == NULL) usage(argv[0]); protocol = protoent->p_proto; break; default: usage(argv[0]); break; } } shost = argv[argc-2]; dhost = argv[argc-1]; // Source address if((hostentry = gethostbyname(shost)) == NULL) ERROR("gethostbyname source address"); memset(&saddr, 0, sizeof(struct sockaddr)); saddr.sin_family = AF_INET; saddr.sin_addr = *((struct in_addr *)hostentry->h_addr); // Destination address if((hostentry = gethostbyname(dhost)) == NULL) ERROR("gethostbyname destination address"); memset(&daddr, 0, sizeof(struct sockaddr)); daddr.sin_family = AF_INET; daddr.sin_addr = *((struct in_addr *)hostentry->h_addr); // MAIN s = open_packet(); for(i = 0; i < amount; i++) { printf("Sending packets with ID %d (frags length=%d, total length=%d)\n", (id + i)%65535, (size<<3), len); send_packet(s, saddr, daddr, protocol, type, (id + i)%65535, size, len); } close(s); return(0); }