diff -ur nmap-3.78/nmap.cc nmap-3.78mm/nmap.cc --- nmap-3.78/nmap.cc 2004-12-30 17:22:19.000000000 +0100 +++ nmap-3.78mm/nmap.cc 2004-12-30 17:20:02.000000000 +0100 @@ -275,6 +275,7 @@ {"data_length", required_argument, 0, 0}, {"rH", no_argument, 0, 0}, {"vv", no_argument, 0, 0}, + {"ff", no_argument, 0, 0}, {"append_output", no_argument, 0, 0}, {"noninteractive", no_argument, 0, 0}, {"ttl", required_argument, 0, 0}, /* Time to live */ @@ -480,6 +481,9 @@ } else if (strcmp(long_options[option_index].name, "vv") == 0) { /* Compatability hack ... ugly */ o.verbose += 2; + } else if (strcmp(long_options[option_index].name, "ff") == 0) { + /* Compatability hack ... ugly */ + o.fragscan += 2; } else { fatal("Unknown long option (%s) given@#!$#$", long_options[option_index].name); } diff -ur nmap-3.78/scan_engine.cc nmap-3.78mm/scan_engine.cc --- nmap-3.78/scan_engine.cc 2004-12-30 17:22:19.000000000 +0100 +++ nmap-3.78mm/scan_engine.cc 2004-12-29 22:42:07.000000000 +0100 @@ -1747,7 +1747,10 @@ probe->setIP(packet, packetlen); hss->lastprobe_sent = probe->sent = USI->now; } - send_ip_packet(USI->rawsd, packet, packetlen); + if (o.fragscan) + send_frag_ip_packet(USI->rawsd, packet, packetlen); + else + send_ip_packet(USI->rawsd, packet, packetlen); free(packet); } } else if (USI->udp_scan) { diff -ur nmap-3.78/tcpip.cc nmap-3.78mm/tcpip.cc --- nmap-3.78/tcpip.cc 2004-12-30 17:22:19.000000000 +0100 +++ nmap-3.78mm/tcpip.cc 2004-12-30 17:26:13.000000000 +0100 @@ -803,6 +803,40 @@ return res; } +/* Create and send all fragments of a pre-built IPv4 packet */ +/* Warning: this damages the packet */ +int send_frag_ip_packet(int sd, u8 *packet, unsigned int packetlen) { + struct ip *ip = (struct ip *) packet; + int datalen = packetlen - sizeof(struct ip); + int fdatalen, res = 0; + + /* Minimal MTU for IPv4 is 68 and maximal IPv4 header size is 60 + * which gives us a right to cut TCP header after 8th byte + * (shouldn't we inflate the header to 60 bytes too?) */ + int mtu = o.fragscan > 1 ? 8 : 16; // here, mtu = MTU - sizeof(struct ip) + + assert(mtu % 8 == 0); // otherwise, we couldn't set proper Fragment offset (ip->ip_off) + + if (packetlen <= sizeof(struct ip) + mtu) + fatal("The packet is too small and can't be fragmented"); + + for (int fragment = 1; fragment * mtu < datalen + mtu; fragment++) { + fdatalen = (fragment * mtu <= datalen ? mtu : datalen % mtu); + ip->ip_len = BSDFIX(fdatalen + sizeof(struct ip)); + ip->ip_off = BSDFIX((fragment-1) * mtu / 8); + if ((fragment-1) * mtu + fdatalen < datalen) + ip->ip_off |= BSDFIX(MORE_FRAGMENTS); +#if HAVE_IP_IP_SUM + ip->ip_sum = in_cksum((unsigned short *)ip, sizeof(struct ip)); +#endif + if (fragment > 1) // shift data payload + memcpy(packet + sizeof(struct ip), packet + sizeof(struct ip) + (fragment - 1) * mtu, fdatalen); + res = send_ip_packet(sd, packet, sizeof(struct ip) + fdatalen); + } + + return res; +} + /* Builds an ICMP packet (including an IP header) by packing the fields with the given information. It allocates a new buffer to store the packet contents, and then returns that buffer. The packet is not @@ -1099,6 +1133,7 @@ return res; } +#if 0 int send_small_fragz_decoys(int sd, const struct in_addr *victim, u32 seq, int ttl, u16 sport, u16 dport, int flags) { int decoy; @@ -1253,6 +1288,7 @@ return 1; } +#endif int send_ip_raw_decoys( int sd, const struct in_addr *victim, int ttl, u8 proto, char *data, u16 datalen) { diff -ur nmap-3.78/tcpip.h nmap-3.78mm/tcpip.h --- nmap-3.78/tcpip.h 2004-11-04 02:23:10.000000000 +0100 +++ nmap-3.78mm/tcpip.h 2004-12-30 12:01:48.000000000 +0100 @@ -549,11 +549,17 @@ /* Send a pre-built IPv4 packet */ int send_ip_packet(int sd, u8 *packet, unsigned int packetlen); +/* Create and send all fragments of the pre-built packet */ +int send_frag_ip_packet(int sd, u8 *packet, unsigned int packetlen); + +#if 0 /* Much of this is swiped from my send_tcp_raw function above, which doesn't support fragmentation */ int send_small_fragz(int sd, struct in_addr *source, const struct in_addr *victim, u32 seq, int ttl, u16 sport, u16 dport, int flags); +#endif + /* Decoy versions of the raw packet sending functions ... */ int send_tcp_raw_decoys( int sd, const struct in_addr *victim, int ttl, u16 sport, u16 dport, u32 seq, u32 ack, u8 flags, @@ -564,8 +570,10 @@ u16 sport, u16 dport, u16 ipid, char *data, u16 datalen); +#if 0 int send_small_fragz_decoys( int sd, const struct in_addr *victim, u32 seq, int ttl, u16 sport, u16 dport, int flags); +#endif int send_ip_raw_decoys( int sd, const struct in_addr *victim, int ttl, u8 proto, char *data, u16 datalen);