diff --git a/CHANGELOG b/CHANGELOG
index 2d078b3ba..da75e767e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,14 @@ o Integrated all of your Q32006 service fingerprint submissions. The
thanks to version detection czar Doug Hoyte for doing this. Notable
changes are described at http://hcsw.org/blog.pl?a=20&b=20 .
+o Nmap now has traceroute support, thanks to an excellent patch by
+ Eddie Bell. The new system uses Nmap data to determine which sort of
+ packets are most likely to slip through the target network and
+ produce useful results. The system is well optimized for speed and
+ bandwidth efficiency, and the clever output system avoids repeating
+ the same initial hops for each target system. Enable this
+ functionality by specifying --traceroute.
+
o Nmap now has a public Subversion (SVN) source code repository. See
the announcement at http://seclists.org/nmap-dev/2006/q4/0253.html
and then the updated usage instructions at
diff --git a/Makefile.in b/Makefile.in
index 17602744a..a4e2094d8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -50,11 +50,11 @@ TARGETNMAPFE=@TARGETNMAPFE@
INSTALLNMAPFE=@INSTALLNMAPFE@
INSTALLNSE=@INSTALLNSE@
-export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc nse_main.cc nse_auxiliar.cc nse_nsock.cc nse_init.cc nse_nmaplib.cc nse_debug.cc nse_bitlib.cc nse_pcrelib.cc nse_string.cc @COMPAT_SRCS@
+export SRCS = main.cc nmap.cc targets.cc tcpip.cc nmap_error.cc utils.cc idle_scan.cc osscan.cc osscan2.cc output.cc scan_engine.cc timing.cc charpool.cc services.cc protocols.cc nmap_rpc.cc portlist.cc NmapOps.cc TargetGroup.cc Target.cc FingerPrintResults.cc service_scan.cc NmapOutputTable.cc MACLookup.cc nmap_tty.cc nmap_dns.cc nse_main.cc nse_auxiliar.cc nse_nsock.cc nse_init.cc nse_nmaplib.cc nse_debug.cc nse_bitlib.cc nse_pcrelib.cc nse_string.cc traceroute.cc @COMPAT_SRCS@
-export HDRS = charpool.h FingerPrintResults.h global_structures.h idle_scan.h MACLookup.h nmap_amigaos.h nmap_dns.h nmap_error.h nmap.h NmapOps.h NmapOutputTable.h nmap_rpc.h nmap_tty.h nmap_winconfig.h osscan.h osscan2.h output.h portlist.h protocols.h scan_engine.h service_scan.h services.h TargetGroup.h Target.h targets.h tcpip.h timing.h utils.h nse_main.h nse_auxiliar.h nse_nsock.h nse_init.h nse_nmaplib.h nse_debug.h nse_macros.h nse_bitlib.h nse_pcrelib.h nse_string.h
+export HDRS = charpool.h FingerPrintResults.h global_structures.h idle_scan.h MACLookup.h nmap_amigaos.h nmap_dns.h nmap_error.h nmap.h NmapOps.h NmapOutputTable.h nmap_rpc.h nmap_tty.h nmap_winconfig.h osscan.h osscan2.h output.h portlist.h protocols.h scan_engine.h service_scan.h services.h TargetGroup.h Target.h targets.h tcpip.h timing.h utils.h nse_main.h nse_auxiliar.h nse_nsock.h nse_init.h nse_nmaplib.h nse_debug.h nse_macros.h nse_bitlib.h nse_pcrelib.h nse_string.h traceroute.h
-OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o osscan2.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o nse_main.o nse_auxiliar.o nse_nsock.o nse_init.o nse_nmaplib.o nse_debug.o nse_bitlib.o nse_pcrelib.o nse_string.o @COMPAT_OBJS@
+OBJS = main.o nmap.o targets.o tcpip.o nmap_error.o utils.o idle_scan.o osscan.o osscan2.o output.o scan_engine.o timing.o charpool.o services.o protocols.o nmap_rpc.o portlist.o NmapOps.o TargetGroup.o Target.o FingerPrintResults.o service_scan.o NmapOutputTable.o MACLookup.o nmap_tty.o nmap_dns.o nse_main.o nse_auxiliar.o nse_nsock.o nse_init.o nse_nmaplib.o nse_debug.o nse_bitlib.o nse_pcrelib.o nse_string.o traceroute.o @COMPAT_OBJS@
# %.o : %.cc -- nope this is a GNU extension
.cc.o:
@@ -110,11 +110,11 @@ debug:
# Make the Nmap tarball
distro:
- cd dev && $(MAKE) distro
+ cd ../nmap-dev && $(MAKE) distro
# Update the web site
web:
- cd dev && $(MAKE) web
+ cd ../nmap-dev && $(MAKE) web
clean: @LUA_CLEAN@ @PCAP_CLEAN@ @PCRE_CLEAN@ @DNET_CLEAN@ nmapfe_clean nsock_clean nbase_clean my_clean
diff --git a/NmapOps.h b/NmapOps.h
index d322ed312..005cb332d 100644
--- a/NmapOps.h
+++ b/NmapOps.h
@@ -301,6 +301,7 @@ class NmapOps {
int resolve_all;
char *dns_servers;
bool log_errors;
+ bool traceroute;
#ifndef NOLUA
int script;
diff --git a/Target.h b/Target.h
index dd3304fcf..c4fee8ed6 100644
--- a/Target.h
+++ b/Target.h
@@ -231,11 +231,11 @@ class Target {
int wierd_responses; /* echo responses from other addresses, Ie a network broadcast address */
unsigned int flags; /* HOST_UP, HOST_DOWN, HOST_FIREWALLED, HOST_BROADCAST (instead of HOST_BROADCAST use wierd_responses */
struct timeout_info to;
+ char *hostname; // Null if unable to resolve or unset
ScriptResults scriptResults;
private:
- char *hostname; // Null if unable to resolve or unset
void Initialize();
void FreeInternal(); // Free memory allocated inside this object
// Creates a "presentation" formatted string out of the IPv4/IPv6 address
diff --git a/docs/nmap.1 b/docs/nmap.1
index 6e820d5e0..6056566ec 100644
--- a/docs/nmap.1
+++ b/docs/nmap.1
@@ -2,7 +2,7 @@
.\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
.\" Instead of manually editing it, you probably should edit the DocBook XML
.\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
-.TH "NMAP" "1" "03/11/2007" "" "Nmap Reference Guide"
+.TH "NMAP" "1" "03/12/2007" "" "Nmap Reference Guide"
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
@@ -669,6 +669,25 @@ option.
By default, Nmap randomizes the scanned port order (except that certain commonly accessible ports are moved near the beginning for efficiency reasons). This randomization is normally desirable, but you can specify
\fB\-r\fR
for sequential port scanning instead.
+.TP
+\fB\-\-traceroute\fR (Trace path to host)
+Traceroutes are performed post\-scan and they uses information from the scan results to determines a valid responsive port and protocol to trace to. It works with all scan types apart from connect scans (\-sT) and idle scans (\-sI). All traces use nmap's dynamic timing model and are performed in parallel.
+.sp
+Traceroute works by sending packets with a low TTL (time\-to\-live) in an attempt to illicit ICMP TTL_EXCCEDED messages from intermediate hops between the scanner and the target host. Standard traceroute implementation start with a TTL of 1 and increment the TTL until the destination host is reached. Nmap's traceroute starts with a high TTL and then decrements the TTL until it reaches 0. Doing it backwards means nmap can employ clever caching algorithms to speed up traces over multiple hosts. On average nmap sends 5\-10 less packet per host, depending on network condition. If a related subnet is being scanned (I.E 192.168.0.0/24) nmap may only have to send a single packet to the majority of hosts.
+.sp
+The output from each trace is consolidated to save space, There are two type of consolidation timed out and reference trace. A reference trace can be considered a cache of hops nmap has seen so far.
+Example\ 14.2.\ Timeout consolidation.sp
+.nf
+ 1 ... Hop 1 timed out
+ 1 ... 6 Hop 1 to 6 timed out
+
+.fi
+Example\ 14.3.\ Reference consolidation (hop cache).sp
+.nf
+ 1 \-\- Hop 1 has been taken from the reference trace
+ 1 \-\-> 6 Hop 1 to 6 have been taken from the reference trace
+
+.fi
.SH "SERVICE AND VERSION DETECTION"
.PP
Point Nmap at a remote machine and it might tell you that ports 25/tcp, 80/tcp, and 53/udp are open. Using its
diff --git a/docs/nmap.dtd b/docs/nmap.dtd
index 796db1e2f..ab465eb00 100644
--- a/docs/nmap.dtd
+++ b/docs/nmap.dtd
@@ -131,7 +131,8 @@
-->
+ tcpsequence | ipidsequence | tcptssequence |
+ hostscript | trace)* ) >
@@ -264,6 +265,25 @@
values CDATA #IMPLIED
>
+
+
+
+
+
+
+
+
+
diff --git a/docs/nmap.xsl b/docs/nmap.xsl
index 3f873e6d9..4f6f417eb 100644
--- a/docs/nmap.xsl
+++ b/docs/nmap.xsl
@@ -690,6 +690,57 @@
+
+
+
+
+ traceroute
+
+ - port:
+ - proto:
+
+ - error:
+
+
+
+
+ | Hop |
+ Rtt |
+ IP |
+ Host |
+
+
+
+
+
+ |
+ -- |
+ |
+ |
+
+
+
+
+ |
+ |
+ |
+ |
+
+
+
+
+ |
+ | | |
+
+
+
+
+
+
+
+
+
+
diff --git a/global_structures.h b/global_structures.h
index 47ab69c7b..139bff9ab 100644
--- a/global_structures.h
+++ b/global_structures.h
@@ -242,6 +242,6 @@ struct scan_lists {
int prot_count;
};
-typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN} stype;
+typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE, REF_TRACEROUTE}stype;
#endif /*GLOBAL_STRUCTURES_H */
diff --git a/nmap.cc b/nmap.cc
index 66be1070d..9904dcc22 100644
--- a/nmap.cc
+++ b/nmap.cc
@@ -107,6 +107,7 @@
#include "timing.h"
#include "NmapOps.h"
#include "MACLookup.h"
+#include "Traceroute.h"
#include "nmap_tty.h"
#include "nmap_dns.h"
#include "nse_main.h"
@@ -225,6 +226,7 @@ printf("%s %s ( %s )\n"
" -sI : Idlescan\n"
" -sO: IP protocol scan\n"
" -b : FTP bounce scan\n"
+ " --traceroute: Trace hop path to each host\n"
"PORT SPECIFICATION AND SCAN ORDER:\n"
" -p : Only scan specified ports\n"
" Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080\n"
@@ -461,6 +463,7 @@ int nmap_main(int argc, char *argv[]) {
char *endptr = NULL;
struct scan_lists *ports = NULL;
TargetGroup *exclude_group = NULL;
+ Traceroute *troute = NULL;
char myname[MAXHOSTNAMELEN + 1];
#if (defined(IN_ADDR_DEEPSTRUCT) || defined( SOLARIS))
/* Note that struct in_addr in solaris is 3 levels deep just to store an
@@ -584,6 +587,7 @@ int nmap_main(int argc, char *argv[]) {
{"thc", no_argument, 0, 0},
{"badsum", no_argument, 0, 0},
{"ttl", required_argument, 0, 0}, /* Time to live */
+ {"traceroute", no_argument, 0, 0},
{"allports", no_argument, 0, 0},
{"version_intensity", required_argument, 0, 0},
{"version-intensity", required_argument, 0, 0},
@@ -833,6 +837,8 @@ int nmap_main(int argc, char *argv[]) {
fatal("Ip options can't be more than 40 bytes long");
if(o.ipoptionslen %4 != 0)
fatal("Ip options must be multiple of 4 (read length is %i bytes)", o.ipoptionslen);
+ } else if(strcmp(long_options[option_index].name, "traceroute") == 0) {
+ o.traceroute = true;
} else {
fatal("Unknown long option (%s) given@#!$#$", long_options[option_index].name);
}
@@ -1186,6 +1192,17 @@ int nmap_main(int argc, char *argv[]) {
}
}
+ if(o.traceroute && (o.idlescan || o.connectscan)) {
+ error("Warning: Traceroute does not support idle or connect scan, disabling...\n");
+ o.traceroute = 0;
+ }
+
+ if(o.traceroute && !o.isr00t) {
+ error("Warning: Traceroute has to be run as root, disabling...\n");
+ o.traceroute = 0;
+ }
+
+
if ((o.pingscan || o.listscan) && (portlist || fastscan)) {
fatal("You cannot use -F (fast scan) or -p (explicit port selection) with PING scan or LIST scan");
}
@@ -1496,7 +1513,7 @@ int nmap_main(int argc, char *argv[]) {
if (currenths->flags & HOST_UP && !o.listscan)
o.numhosts_up++;
- if (o.pingscan || o.listscan) {
+ if ((o.pingscan && !o.traceroute) || o.listscan) {
/* We're done with the hosts */
log_write(LOG_XML, "");
write_host_status(currenths, o.resolve_all);
@@ -1569,6 +1586,33 @@ int nmap_main(int argc, char *argv[]) {
if (o.af() == AF_INET && o.RawScan())
o.decoys[o.decoyturn] = Targets[0]->v4source();
+ /* ping scan traceroutes */
+ if(o.traceroute && o.pingscan) {
+ /* Assume that all targets in a group use the same device */
+ troute = new Traceroute(Targets[0]->deviceName(), Targets[0]->ifType());
+ troute->trace(Targets);
+ troute->resolveHops();
+
+ /* print ping traceroutes, making sure the reference
+ * trace is first */
+ while(!Targets.empty()) {
+ currenths = *Targets.begin();
+ log_write(LOG_XML, "");
+ write_host_status(currenths, o.resolve_all);
+ printmacinfo(currenths);
+ troute->outputTarget(currenths);
+ log_write(LOG_XML, "\n");
+ log_write(LOG_STDOUT|LOG_SKID|LOG_PLAIN,"\n");
+ delete currenths;
+ Targets.erase(Targets.begin());
+ }
+ o.numhosts_scanning = 0;
+ log_flush_all();
+ delete troute;
+ troute = NULL;
+ continue;
+ }
+
/* I now have the group for scanning in the Targets vector */
// Ultra_scan sets o.scantype for us so we don't have to worry
@@ -1633,6 +1677,12 @@ int nmap_main(int argc, char *argv[]) {
if (o.osscan == OS_SCAN_DEFAULT || o.osscan == OS_SCAN_SYS_2_ONLY)
os_scan2(Targets);
+ if(o.traceroute) {
+ troute = new Traceroute(Targets[0]->deviceName(), Targets[0]->ifType());
+ troute->trace(Targets);
+ troute->resolveHops();
+ }
+
for(targetno = 0; targetno < Targets.size(); targetno++) {
currenths = Targets[targetno];
@@ -1673,6 +1723,9 @@ int nmap_main(int argc, char *argv[]) {
#endif
}
+ if(troute)
+ troute->outputTarget(currenths);
+
if (o.debugging)
log_write(LOG_STDOUT, "Final times for host: srtt: %d rttvar: %d to: %d\n",
currenths->to.srtt, currenths->to.rttvar, currenths->to.timeout);
@@ -1690,6 +1743,9 @@ int nmap_main(int argc, char *argv[]) {
o.numhosts_scanning = 0;
} while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned);
+ if(troute)
+ delete troute;
+
delete hstate;
if (exclude_group)
delete[] exclude_group;
@@ -2171,6 +2227,8 @@ char *scantype2str(stype scantype) {
case SERVICE_SCAN: return "Service Scan"; break;
case OS_SCAN: return "OS Scan"; break;
case SCRIPT_SCAN: return "Script Scan"; break;
+ case TRACEROUTE: return "Traceroute" ; break;
+ case REF_TRACEROUTE: return "Reference Traceroute"; break;
default: assert(0); break;
}
diff --git a/nmap_dns.cc b/nmap_dns.cc
index 6d0262317..83cf66ae1 100644
--- a/nmap_dns.cc
+++ b/nmap_dns.cc
@@ -142,6 +142,9 @@
// doug at hcsw.org
// http://www.hcsw.org
+/*
+ * DNS Caching and ageing added by Eddie Bell ejlbell@gmail.com 2007
+ */
// TODO:
//
@@ -158,6 +161,7 @@
#include
#include
#include
+#include
#include "nmap.h"
#include "NmapOps.h"
@@ -267,6 +271,7 @@ struct request_s {
struct host_elem_s {
char *name;
u32 addr;
+ u8 cache_hits;
};
@@ -292,13 +297,13 @@ static ScanProgressMeter *SPM;
//------------------- Prototypes and macros ---------------------
static void put_dns_packet_on_wire(request *req);
+static char *lookup_etchosts(u32 ip);
+static void addto_etchosts(u32 ip, const char *hname);
#define ACTION_FINISHED 0
#define ACTION_CNAME_LIST 1
#define ACTION_TIMEOUT 2
-
-
//------------------- Misc code ---------------------
static void output_summary() {
@@ -370,7 +375,8 @@ static void do_possible_writes() {
}
if (tpreq) {
- if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: TRANSMITTING for <%s> (server <%s>)\n", tpreq->targ->targetipstr() , tpserv->hostname);
+ if (o.debugging >= TRACE_DEBUG_LEVEL)
+ log_write(LOG_STDOUT, "mass_rdns: TRANSMITTING for <%s> (server <%s>)\n", tpreq->targ->targetipstr() , tpserv->hostname);
stat_trans++;
put_dns_packet_on_wire(tpreq);
}
@@ -398,7 +404,6 @@ static void put_dns_packet_on_wire(request *req) {
struct timeval now, timeout;
ip = (u32) ntohl(req->targ->v4host().s_addr);
-
packet[0] = (req->id >> 8) & 0xFF;
packet[1] = req->id & 0xFF;
plen += 2;
@@ -527,13 +532,18 @@ static int process_result(u32 ia, char *result, int action, u16 id) {
if (id == tpreq->id) {
- if (ia != 0 && (u32) (tpreq->targ->v4host().s_addr) != ia) continue;
+ if (ia != 0 && tpreq->targ->v4host().s_addr != ia)
+ continue;
if (action == ACTION_CNAME_LIST || action == ACTION_FINISHED) {
tpserv->capacity += CAPACITY_UP_STEP;
check_capacities(tpserv);
- if (result) tpreq->targ->setHostName(result);
+ if (result) {
+ tpreq->targ->setHostName(result);
+ addto_etchosts(tpreq->targ->v4hostip()->s_addr, result);
+ }
+
tpserv->in_process.remove(tpreq);
tpserv->reqs_on_wire--;
@@ -977,6 +987,7 @@ static void parse_etchosts(char *fname) {
he = new host_elem;
he->name = strdup(hname);
he->addr = (u32) ia.s_addr;
+ he->cache_hits = 0;
etchosts[he->addr % HASH_TABLE_SIZE].push_front(he);
}
}
@@ -1002,19 +1013,66 @@ void free_etchosts() {
}
}
+/* Executed when the DNS cache is full, ages entries
+ * and removes any with a cache hit of 0 (the least used) */
+bool remove_and_age(host_elem *host) {
+ if(host->cache_hits) {
+ host->cache_hits /=2;
+ return false;
+ } else
+ return true;
+}
+/* Add to the dns cache. If there is no space we age and
+ * remove the least frequently used entries until there
+ * is space */
+static void addto_etchosts(u32 ip, const char *hname) {
+ static u16 total_size = 0;
+ std::list::iterator it;
+ host_elem *he;
+ int i;
+
+ if(lookup_etchosts(ip) != NULL)
+ return;
+
+ while(total_size >= HASH_TABLE_SIZE) {
+ for(i = 0; i < HASH_TABLE_SIZE; i++) {
+ while((it = find_if(etchosts[i].begin(), etchosts[i].end(), remove_and_age)) != etchosts[i].end()) {
+ etchosts[i].erase(it);
+ total_size--;
+ }
+ }
+ }
+ he = new host_elem;
+ he->name = strdup(hname);
+ he->addr = ip;
+ he->cache_hits = 0;
+ etchosts[ip % HASH_TABLE_SIZE].push_back(he);
+ total_size++;
+}
+
+/* Search for a hostname in the cache and increment
+ * its cache hit counter if found */
static char *lookup_etchosts(u32 ip) {
std::list::iterator hostI;
host_elem *tpelem;
for(hostI = etchosts[ip % HASH_TABLE_SIZE].begin(); hostI != etchosts[ip % HASH_TABLE_SIZE].end(); hostI++) {
tpelem = *hostI;
- if (tpelem->addr == ip) return tpelem->name;
+ if (tpelem->addr == ip) {
+ if(tpelem->cache_hits < UCHAR_MAX)
+ tpelem->cache_hits++;
+ return tpelem->name;
+ }
}
-
return NULL;
}
+/* External interface to dns cache */
+const char *lookup_cached_host(u32 ip) {
+ const char *tmp = lookup_etchosts(ip);
+ return tmp==NULL?"":tmp;
+}
static void etchosts_init(void) {
static int initialized = 0;
@@ -1119,7 +1177,7 @@ static void nmap_mass_rdns_core(Target **targets, int num_targets) {
for(hostI = targets; hostI < targets+num_targets; hostI++) {
if (!((*hostI)->flags & HOST_UP) && !o.resolve_all) continue;
- // See if it's in /etc/hosts
+ // See if it's in /etc/hosts or cached
tpname = lookup_etchosts((u32) (*hostI)->v4hostip()->s_addr);
if (tpname) {
(*hostI)->setHostName(tpname);
diff --git a/nmap_dns.h b/nmap_dns.h
index ba9904da6..3ee5d3919 100644
--- a/nmap_dns.h
+++ b/nmap_dns.h
@@ -98,7 +98,8 @@
#include "Target.h"
void nmap_mass_rdns(Target ** targets, int num_targets);
-void free_dns_servers();
+const char *lookup_cached_host(u32 ip);
+void free_dns_servers();
void free_etchosts();
diff --git a/tcpip.cc b/tcpip.cc
index e9dc559b8..489436fd7 100644
--- a/tcpip.cc
+++ b/tcpip.cc
@@ -1417,11 +1417,11 @@ char *ping = (char *) &pingpkt;
icmplen = 20;
memset(datastart, 0, 12);
datastart += 12;
- datalen -= 12;
+ //datalen -= 12;
} else if (ptype == 17 && pcode == 0) /* icmp netmask req */ {
icmplen = 12;
*datastart++ = 0;
- datalen -= 4;
+ //datalen -= 4;
} else
fatal("Unknown icmp type/code (%d/%d) in build_icmp_raw", ptype, pcode);