Nmap Development mailing list archives

Re: Info about your patch


From: R Andersson <listbox () pole-position org>
Date: Sun, 09 Mar 2003 23:29:13 +0100

OK, here it is. I cc nmap-dev in case others are interested too. This is just experimental, some parts are really not good code yet and some output "design issues" are not final.

This patch adds the following two options:

--showallports
This stops nmap from collating ports like "the 13 ports not shown are in state: filtered". Otherwise we will miss the extra info from the next option:

--clarify
This does two things: first, it helps the user parse the results by telling what each state really means. For example, when doing a UDP scan, it says "open means there was no answer" which is pretty important to understand. Second, any received ICMP messages are shown, e.g. "ICMP administratively prohibited from 172.22.33.1". This is also written to the XML output.

I'm not working on this right now but some issues remains, some was discussed around last December 19 on nmap-dev. Also, any real programmer would probably cry when reading my code.

Note that I haven't updated this to the latest nmap versions.

/R


Daniel Fdez. Bleda wrote:
I would be very happy if you could send me something to start with.
I'm interested in apply some patch to know precisely what I think you want,
know when a router/FW is doing NAT and obtain more info about the machines
beyond the packet filter to identify configurations of NAT.
If you send me also any documentation about this theme that you were using
or a full explanation of what your code should do.

Best regards,

Daniel


-----Mensaje original-----
De: R Andersson [mailto:listbox () pole-position org]
Enviado el: viernes, 07 de marzo de 2003 13:07
Para: Daniel Fdez. Bleda
Asunto: Re: Info about your patch


The patch Fyodor applied is just a tiny (but important) bugfix. Without
it, nmap regarded the port as closed even though the answer came from an
intermediate host (simply put, a firewall).

We talked earlier about a relate issue; that nmap should tell us when
there was answers from intermediates. So instead of just saying
"filtered" it could say something like "filtered by 172.29.31.127". I
have a working patch that adds this and more. The tricky part is how to
put it in human and XML output. I will post it to the list when it's
good enough.

Right now I'm not working on it though. If you want to, I could send you
the current "beta".

/R

Daniel Fdez. Bleda wrote:

Hi Rasmus,

We were talking some months ago to add some improvement in nmap, that I
think you finally add in version 3.10ALPHA7 as says the changelog:

o Applied patch from R Anderson (listbox () pole-position org) which
 improves the way ICMP port unreachables from intermediate hosts
 are handled during UDP scans.

I would very interested if you could explain me how that patch finally
works, and what are the correct params in nmap to take profit of it.
diff -ruBN nmap-3.10ALPHA7/Makefile.in nmap-3.10ALPHA7-aware/Makefile.in
--- nmap-3.10ALPHA7/Makefile.in Wed Dec 18 07:09:44 2002
+++ nmap-3.10ALPHA7-aware/Makefile.in   Thu Dec 19 10:04:18 2002
@@ -1,4 +1,4 @@
-NMAP_VERSION = 3.10ALPHA7
+NMAP_VERSION = 3.10ALPHA7a
 NMAP_NAME= nmap
 NMAP_URL= www.insecure.org/nmap/
 NMAP_PLATFORM=@host@
diff -ruBN nmap-3.10ALPHA7/NmapOps.cc nmap-3.10ALPHA7-aware/NmapOps.cc
--- nmap-3.10ALPHA7/NmapOps.cc  Wed Oct 23 10:51:57 2002
+++ nmap-3.10ALPHA7-aware/NmapOps.cc    Thu Dec 19 10:04:18 2002
@@ -117,6 +117,8 @@
 #endif
   debugging = DEBUGGING;
   verbose = DEBUGGING;
+  clarify = 0;
+  showallports = 0;
   randomize_hosts = 0;
   spoofsource = 0;
   device[0] = '\0';
diff -ruBN nmap-3.10ALPHA7/NmapOps.h nmap-3.10ALPHA7-aware/NmapOps.h
--- nmap-3.10ALPHA7/NmapOps.h   Wed Oct 23 10:51:57 2002
+++ nmap-3.10ALPHA7-aware/NmapOps.h     Thu Dec 19 10:04:18 2002
@@ -80,6 +80,8 @@
   // setPacketTrace(false) has been called
   void setPacketTrace(bool pt) { pTrace = pt;  }
   int verbose;
+  int clarify;
+  int showallports;
   int randomize_hosts;
   int spoofsource; /* -S used */
   char device[64];
diff -ruBN nmap-3.10ALPHA7/TODO.txt nmap-3.10ALPHA7-aware/TODO.txt
--- nmap-3.10ALPHA7/TODO.txt    Thu Jan  1 01:00:00 1970
+++ nmap-3.10ALPHA7-aware/TODO.txt      Thu Dec 19 11:39:18 2002
@@ -0,0 +1,5 @@
+How do we handle ICMP (intermediates) XML output if not --showallports?
+Maybe we could always show all ports for XML?
+
+Should we include non-intermediate ICMP in XML output? 
+Is the schema made for this, i.e. using <filteredby> without the srcipaddr property, or possibly using it with the 
targets IP
diff -ruBN nmap-3.10ALPHA7/Target.cc nmap-3.10ALPHA7-aware/Target.cc
--- nmap-3.10ALPHA7/Target.cc   Tue Aug 27 23:43:23 2002
+++ nmap-3.10ALPHA7-aware/Target.cc     Thu Dec 19 10:04:18 2002
@@ -72,6 +72,7 @@
   bzero(&sourcesock, sizeof(sourcesock));
   targetsocklen = sourcesocklen = 0;
   targetipstring[0] = '\0';
+  icmpresponse = intermediateresp = 0;
 }
 
 void Target::Recycle() {
diff -ruBN nmap-3.10ALPHA7/Target.h nmap-3.10ALPHA7-aware/Target.h
--- nmap-3.10ALPHA7/Target.h    Tue Aug 27 23:43:23 2002
+++ nmap-3.10ALPHA7-aware/Target.h      Thu Dec 19 10:04:18 2002
@@ -116,6 +116,8 @@
   int timedout; /* Nonzero if continued scanning should be aborted due to
                   timeout  */
   char device[64]; /* The device we transmit on */
+  unsigned int icmpresponse;  // Number of unreachables from this host
+  unsigned int intermediateresp;  // Number of ICMP unreachables from intermediate routers
 
  private:
   char *hostname; // Null if unable to resolve or unset
diff -ruBN nmap-3.10ALPHA7/idle_scan.cc nmap-3.10ALPHA7-aware/idle_scan.cc
--- nmap-3.10ALPHA7/idle_scan.cc        Mon Sep 16 04:54:43 2002
+++ nmap-3.10ALPHA7-aware/idle_scan.cc  Thu Dec 19 10:04:18 2002
@@ -853,10 +853,10 @@
   }
 
   if (firstHalfSz == 1 && flatcount1 == 1) 
-    addport(&target->ports, ports[0], IPPROTO_TCP, NULL, PORT_OPEN);
+    addport(&target->ports, ports[0], IPPROTO_TCP, NULL, PORT_OPEN, 0, 0);
   
   if ((secondHalfSz == 1) && flatcount2 == 1) 
-    addport(&target->ports, ports[firstHalfSz], IPPROTO_TCP, NULL, PORT_OPEN);
+    addport(&target->ports, ports[firstHalfSz], IPPROTO_TCP, NULL, PORT_OPEN, 0, 0);
   return totalfound;
 
 }
@@ -932,7 +932,7 @@
   for(portidx = 0; portidx < numports; portidx++) {
     if (lookupport(&target->ports, portarray[portidx], IPPROTO_TCP) == NULL) {
       addport(&target->ports, portarray[portidx], IPPROTO_TCP, NULL,
-             PORT_CLOSED);
+             PORT_CLOSED, 0, 0);
     }
   }
 
diff -ruBN nmap-3.10ALPHA7/nmap.cc nmap-3.10ALPHA7-aware/nmap.cc
--- nmap-3.10ALPHA7/nmap.cc     Wed Dec 18 07:10:07 2002
+++ nmap-3.10ALPHA7-aware/nmap.cc       Thu Dec 19 11:23:56 2002
@@ -204,6 +204,8 @@
     {"vv", no_argument, 0, 0},
     {"append_output", no_argument, 0, 0},
     {"noninteractive", no_argument, 0, 0},
+    {"clarify", no_argument, 0, 0},
+    {"showallports", no_argument, 0, 0},
 #ifdef WIN32
     {"win_list_interfaces", no_argument, 0, 0},
     {"win_norawsock", no_argument, 0, 0}, 
@@ -366,6 +368,10 @@
       } else if (strcmp(long_options[option_index].name, "vv") == 0) {
        /* Compatability hack ... ugly */
        o.verbose += 2;
+      } else if (strcmp(long_options[option_index].name, "clarify") == 0) {
+        o.clarify = 1;
+      } else if (strcmp(long_options[option_index].name, "showallports") == 0) {
+        o.showallports = 1;
       } else {
        fatal("Unknown long option (%s) given@#!$#$", long_options[option_index].name);
       }
@@ -732,6 +738,43 @@
     }
   }
 
+  if (o.clarify) {
+    log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\nNote: In this scan, the states has the following meaning:\n");
+    if (o.udpscan) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"UDP:\t\"open\" means we got no answer\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"closed\" means we got an ICMP \"protocol unreachable\" from the 
target\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"filtered\" means some other ICMP message was received\n");
+      if (o.synscan || o.connectscan || o.finscan || o.xmasscan || o.nullscan || o.maimonscan || o.ackscan || 
o.windowscan)
+       log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n");
+    }
+    if (o.synscan || o.connectscan) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"TCP:\t\"open\" means we received an \"ACK\"\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"closed\" means we received a \"RST\"\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"filtered\" means we got no answer\n");
+    }
+    if (o.finscan || o.xmasscan || o.nullscan || o.maimonscan) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"TCP:\t\"open\" means we got no answer\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"closed\" means we received a \"RST\"\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"filtered\" means some ICMP message was received\n");
+    }
+    if (o.ackscan) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"TCP:\t\"unfiltered\" means we received a \"RST\"\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"filtered\" means we got no answer\n");
+    }
+    if (o.windowscan) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"TCP:\t\"open\" means \"windows size reset\"\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"closed\" means \"windows size intact\"\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"unfiltered\" means we received a \"RST\"\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"filtered\" means we got no answer\n");
+    }
+    if (o.ipprotscan) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"open\" means we got no answer\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"closed\" means we got an ICMP \"protocol unreachable\" from the 
target\n");
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\t\"filtered\" means some other ICMP message was received\n");
+    }
+    log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n");
+  }
+
 #if HAVE_SIGNAL
   signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE so our program doesn't crash because
                               of it, but we really shouldn't get an unsuspected
@@ -1230,6 +1273,8 @@
         "  -iL <inputfile> Get targets from file; Use '-' for stdin\n"
         "* -S <your_IP>/-e <devicename> Specify source address or network interface\n"
         "  --interactive Go into interactive mode (then press h for help)\n"
+        "  --clarify Be more descriptive about states and filters\n"
+        "  --showallports Print all ports in table, don't collate\n"
          WIN32_PRINTF
         "Example: nmap -v -sS -O www.my.com 192.168.0.0/16 '192.88-90.*.*'\n"
         "SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES \n", NMAP_VERSION);
@@ -1515,6 +1560,29 @@
   return "unknown";
 }
 
+char *icmp3code2str(int code) {
+  if (code / 256 != 3) return "ERROR, not an unreachable!";
+  switch(code & 255) {
+  case ICMP_NET_UNREACH: return  "ICMP net unreachable"; break;
+  case ICMP_HOST_UNREACH: return  "ICMP host unreachable"; break;
+  case ICMP_PROT_UNREACH: return  "ICMP protocol unreachable"; break;
+  case ICMP_PORT_UNREACH: return  "ICMP port unreachable"; break;
+  case ICMP_FRAG_NEEDED: return  "ICMP fragmentation needed"; break;
+  case ICMP_SR_FAILED: return  "ICMP source route failed"; break;
+  case ICMP_NET_UNKNOWN: return  "ICMP network unknown"; break;
+  case ICMP_HOST_UNKNOWN: return  "ICMP host unknown"; break;
+  case ICMP_HOST_ISOLATED: return  "ICMP host isolated"; break;
+  case ICMP_NET_ANO: return  "ICMP network prohibited"; break;
+  case ICMP_HOST_ANO: return "ICMP host prohibited"; break;
+  case ICMP_NET_UNR_TOS: return "ICMP net+tos unreachable"; break;
+  case ICMP_HOST_UNR_TOS: return "ICMP host+tos unreachable"; break;
+  case ICMP_PKT_FILTERED: return "ICMP administratively prohibited"; break;
+  case ICMP_PREC_VIOLATION: return "ICMP precedence violation"; break;
+  case ICMP_PREC_CUTOFF: return "ICMP precedence cutoff"; break;
+  default: return "unknown"; break;
+  }
+  return "unknown";
+}
 
 /* Checks whether the identd port (113) is open on the target machine.  No
    sense wasting time trying it for each good port if it is down! */
diff -ruBN nmap-3.10ALPHA7/nmap.h nmap-3.10ALPHA7-aware/nmap.h
--- nmap-3.10ALPHA7/nmap.h      Wed Dec 18 08:57:48 2002
+++ nmap-3.10ALPHA7-aware/nmap.h        Thu Dec 19 10:04:18 2002
@@ -415,6 +415,7 @@
 char *grab_next_host_spec(FILE *inputfd, int argc, char **fakeargv);
 int parse_targets(struct targets *targets, char *h);
 char *statenum2str(int state);
+char *icmp3code2str(int code);
 char *scantype2str(stype scantype);
 void sigdie(int signo);
 void reaper(int signo);
diff -ruBN nmap-3.10ALPHA7/output.cc nmap-3.10ALPHA7-aware/output.cc
--- nmap-3.10ALPHA7/output.cc   Mon Sep  9 09:59:51 2002
+++ nmap-3.10ALPHA7-aware/output.cc     Thu Dec 19 11:24:36 2002
@@ -82,11 +82,11 @@
   assert(numignoredports <= plist->numports);
 
 
-  log_write(LOG_XML, "<ports><extraports state=\"%s\" count=\"%d\" />\n", 
-           statenum2str(currenths->ports.ignored_port_state), 
-           numignoredports);
+  log_write(LOG_XML, "<ports>");
+  if (!o.showallports) log_write(LOG_XML, "<extraports state=\"%s\" count=\"%d\" />\n", 
+         statenum2str(currenths->ports.ignored_port_state), numignoredports);
 
-  if (numignoredports == plist->numports) {
+  if (numignoredports == plist->numports && !o.showallports) {
     log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,
               "%s %d scanned %s on %s %s: %s\n",
              (numignoredports == 1)? "The" : "All", numignoredports,
@@ -94,6 +94,14 @@
              currenths->NameIP(hostname, sizeof(hostname)), 
              (numignoredports == 1)? "is" : "are", 
              statenum2str(currenths->ports.ignored_port_state));
+  if (currenths->icmpresponse) {
+    log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Number of ICMP unreachables from this host: %d\n", 
currenths->icmpresponse);
+  } else {
+    if (o.udpscan || o.xmasscan || o.ipprotscan || o.finscan || o.nullscan ) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Note: no ICMP unreachables seen from the host.\n");
+    }
+  }
+  if (currenths->intermediateresp) log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Number of unreachables from 
intermediates: %d\n", currenths->intermediateresp);
     log_write(LOG_MACHINE,"Host: %s (%s)\tStatus: Up", 
              currenths->targetipstr(), currenths->HostName());
     log_write(LOG_XML, "</ports>\n");
@@ -106,16 +114,25 @@
   log_write(LOG_MACHINE,"Host: %s (%s)", currenths->targetipstr(), 
            currenths->HostName());
   
-  if (numignoredports > 0) {
+  if (numignoredports > 0 && !o.showallports) {
     log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"(The %d %s%s scanned but not shown below %s in state: %s)\n", 
numignoredports, o.ipprotscan?"protocol":"port", (numignoredports == 1)? "" : "s", (numignoredports == 1)? "is" : 
"are", statenum2str(plist->ignored_port_state));
   }
 
   if (o.ipprotscan) {
     log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Protocol   State       Name");
+    if ((currenths->intermediateresp || currenths->icmpresponse) && o.clarify) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"                    ICMP");
+    }
   } else if (!o.rpcscan) {  
     log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Port       State       Service");
+    if ((currenths->intermediateresp || currenths->icmpresponse) && o.clarify) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"                 ICMP");
+    }
   } else {
     log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Port       State       Service (RPC)");
+    if ((currenths->intermediateresp || currenths->icmpresponse) && o.clarify) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"           ICMP");
+    }
   }
   log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%s", (o.identscan)? ((o.rpcscan)? "           Owner\n" : "                 
Owner\n") :"\n");
   log_write(LOG_MACHINE,"\t%s: ", (o.ipprotscan)? "Protocols" : "Ports" );
@@ -127,14 +144,38 @@
     for (portno = 1; portno < 256; portno++) {
       if (!plist->ip_prots[portno]) continue;
       current = plist->ip_prots[portno];
-      if (current->state != plist->ignored_port_state) {
+      if ((current->state != plist->ignored_port_state) || o.showallports) {
        if (!first) log_write(LOG_MACHINE,", ");
        else first = 0;
        state = statenum2str(current->state);
        proto = nmap_getprotbynum(htons(current->portno));
        snprintf(portinfo, sizeof(portinfo), "%-24s",
                 proto?proto->p_name: "unknown");
-       log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%-11d%-12s%-24s\n", portno, state, portinfo);
+       log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%-11d%-12s%-24s", portno, state, portinfo);
+       if (o.clarify && current->icmpresp) {
+         if (current->intermediateip) {
+           if (current->icmpresp / 256 == 3) {
+             log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%s from %s",
+                       icmp3code2str(current->icmpresp),
+                       inet_ntoa(inet_makeaddr(htonl(current->intermediateip),0)));
+           } else {
+             log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"ICMP %d/%d from %s",
+                       (current->icmpresp / 256),
+                       (current->icmpresp & 255),
+                       inet_ntoa(inet_makeaddr(htonl(current->intermediateip),0)));
+           }
+         } else {
+           if (current->icmpresp / 256 == 3) {
+             log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%s",
+                       icmp3code2str(current->icmpresp));
+           } else {
+             log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"ICMP %d/%d",
+                       (current->icmpresp / 256),
+                       (current->icmpresp & 255));
+           }
+         }
+       }
+       log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n");
        log_write(LOG_MACHINE,"%d/%s/%s/", current->portno, state, 
                  (proto)? proto->p_name : "");
        log_write(LOG_XML, "<port protocol=\"ip\" portid=\"%d\"><state state=\"%s\" />", current->portno, state);
@@ -150,7 +191,7 @@
        current = protoarrays[protocount][portno];
       else continue;
       
-      if (current->state != plist->ignored_port_state) {    
+      if ((current->state != plist->ignored_port_state) || o.showallports) {    
        if (!first) log_write(LOG_MACHINE,", ");
        else first = 0;
        strcpy(protocol,(current->proto == IPPROTO_TCP)? "tcp": "udp");
@@ -194,6 +235,16 @@
          strcpy(rpcmachineinfo, "");
        }
        log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%-11s%-12s%-24s", portinfo, state, serviceinfo);
+       if (o.clarify && current->icmpresp) {
+         if (current->intermediateip) {
+           log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%s from %s",
+                     icmp3code2str(current->icmpresp),
+                     inet_ntoa(inet_makeaddr(htonl(current->intermediateip),0)));
+         } else {
+           log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%s",
+                     icmp3code2str(current->icmpresp));
+         }
+       }
        log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"%s\n", (current->owner)? current->owner : "");
        
        log_write(LOG_MACHINE,"%d/%s/%s/%s/%s/%s//", current->portno, state, 
@@ -202,6 +253,18 @@
        
        log_write(LOG_XML, "<port protocol=\"%s\" portid=\"%d\">", protocol, current->portno);
        log_write(LOG_XML, "<state state=\"%s\" />", state);
+       if (current->icmpresp) {
+         if (current->intermediateip) {
+           log_write(LOG_XML,
+                     "<filteredby><packet proto=\"ICMP\" type=\"%d\" code=\"%d\" name=\"%s\" srcipaddr=\"%s\" 
ip_v=\"4\" />\n</filteredby>\n",
+                     current->icmpresp / 256, current->icmpresp & 255, icmp3code2str(current->icmpresp),
+                     inet_ntoa(inet_makeaddr(htonl(current->intermediateip),0)));
+         } else {
+           log_write(LOG_XML,
+                     "<filteredby><packet proto=\"ICMP\" type=\"%d\" code=\"%d\" name=\"%s\" ip_v=\"4\" 
/>\n</filteredby>\n",
+                     current->icmpresp / 256, current->icmpresp & 255, icmp3code2str(current->icmpresp));
+         }
+       }
        if (current->owner && *current->owner) {
          log_write(LOG_XML, "<owner name=\"%s\" />", current->owner);
        }
@@ -217,8 +280,19 @@
     }
    }
   }
+  if (currenths->icmpresponse) {
+    log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Number of ICMP unreachables from this host: %d\n", 
currenths->icmpresponse);
+  } else {
+    if (o.udpscan || o.xmasscan || o.ipprotscan || o.finscan || o.nullscan ) {
+      log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"Note: no ICMP unreachables seen from the host.\n");
+    }
+  }
+  if (currenths->intermediateresp) log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,
+      "Number of unreachables from intermediates: %d\n",
+      currenths->intermediateresp);
   /*  log_write(LOG_NORMAL|LOG_SKID|LOG_STDOUT,"\n"); */
-  log_write(LOG_MACHINE, "\tIgnored State: %s (%d)", statenum2str(plist->ignored_port_state), 
plist->state_counts[plist->ignored_port_state]);
+  if (!o.showallports) log_write(LOG_MACHINE, "\tIgnored State: %s (%d)",
+    statenum2str(plist->ignored_port_state), plist->state_counts[plist->ignored_port_state]);
   log_write(LOG_XML, "</ports>\n");
 }
 
diff -ruBN nmap-3.10ALPHA7/portlist.cc nmap-3.10ALPHA7-aware/portlist.cc
--- nmap-3.10ALPHA7/portlist.cc Mon Nov 11 19:03:45 2002
+++ nmap-3.10ALPHA7-aware/portlist.cc   Thu Dec 19 10:04:18 2002
@@ -59,7 +59,7 @@
 
 /* gawd, my next project will be in c++ so I don't have to deal with
    this crap ... simple linked list implementation */
-int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state) {
+int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state, in_addr_t intermediateip, int icmpresp) {
   struct port *current = NULL;
   struct port **portarray = NULL;
   char msg[128];
@@ -133,6 +133,8 @@
   
   plist->state_counts[state]++;
   current->state = state;
+  current->icmpresp = icmpresp;
+  current->intermediateip = intermediateip;
   if (protocol == IPPROTO_TCP) {
     plist->state_counts_tcp[state]++;
   } else if (protocol == IPPROTO_UDP) {
diff -ruBN nmap-3.10ALPHA7/portlist.h nmap-3.10ALPHA7-aware/portlist.h
--- nmap-3.10ALPHA7/portlist.h  Tue Aug 27 23:43:23 2002
+++ nmap-3.10ALPHA7-aware/portlist.h    Thu Dec 19 11:17:10 2002
@@ -48,6 +48,7 @@
 #define PORTLIST_H
 
 #include <nbase.h>
+#include <netinet/in.h>
 
 /* struct port stuff */
 #define PORT_UNKNOWN 0
@@ -80,7 +81,8 @@
   unsigned int rpc_highver;
   int state; 
   int confidence; /* How sure are we about the state? */
-
+  int icmpresp; /* The type*256+code of an ICMP packet we received for this port */
+  in_addr_t intermediateip;    /* The IP of an intermediate router that answered for this port */
   struct port *next; /* Internal use only -- we sometimes like to link them
                        together */
 };
@@ -100,7 +102,7 @@
   int numports; /* Total number of ports in list in ANY state */
 } portlist;
 
-int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state);
+int addport(portlist *plist, u16 portno, u8 protocol, char *owner, int state, in_addr_t intermediateip, int icmpresp);
 int deleteport(portlist *plist, u16 portno, u8 protocol);
 
 /* A function for iterating through the ports.  Give NULL for the
diff -ruBN nmap-3.10ALPHA7/scan_engine.cc nmap-3.10ALPHA7-aware/scan_engine.cc
--- nmap-3.10ALPHA7/scan_engine.cc      Wed Dec 18 07:10:07 2002
+++ nmap-3.10ALPHA7-aware/scan_engine.cc        Thu Dec 19 11:19:19 2002
@@ -64,7 +64,7 @@
 static void posportupdate(Target *target, struct portinfo *current, 
                   int trynum, struct portinfo *scan,
                   struct scanstats *ss ,stype scantype, int newstate,
-                  struct portinfolist *pil, struct connectsockinfo *csi) {
+                  struct portinfolist *pil, struct connectsockinfo *csi, in_addr_t intermediateip, int icmpresp) {
   static int tryident = -1;
   static u32 lasttarget = 0;
   struct sockaddr_in mysock;
@@ -180,7 +180,7 @@
   current->state = newstate;
   current->next = -1;
   current->prev = -1;
-  addport(&target->ports, current->portno, IPPROTO_TCP, owner, newstate);
+  addport(&target->ports, current->portno, IPPROTO_TCP, owner, newstate, intermediateip, icmpresp);
   return;
 }
 
@@ -277,7 +277,7 @@
                log_write(LOG_STDOUT, "Bad port %lu caught by 0-byte write: ", current->portno);
                perror("");
              }
-             posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_CLOSED, pil, csi);
+             posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_CLOSED, pil, csi, 0, 0);
            } else {
              if (getpeername(sd, (struct sockaddr *) &sin, &sinlen) < 0) {
                pfatal("error in getpeername of connect_results for port %hu", current->portno);
@@ -299,20 +299,20 @@
                /* Linux 2.2 bug can lead to bogus successful connect()ions
                   in this case -- we treat the port as bogus even though it
                   is POSSIBLE that this is a real connection */
-               posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_CLOSED, pil, csi);
+               posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_CLOSED, pil, csi, 0, 0);
              } else {
-               posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_OPEN, pil, csi);
+               posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_OPEN, pil, csi, 0, 0);
              }
            }
          } else {
-           posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_OPEN, pil, csi);
+           posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_OPEN, pil, csi, 0, 0);
          }
 #else
-         posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_OPEN, pil, csi);
+         posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_OPEN, pil, csi, 0, 0);
 #endif
          break;
        case ECONNREFUSED:
-         posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_CLOSED, pil, csi);
+         posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_CLOSED, pil, csi, 0, 0);
          break;
        case EHOSTUNREACH:
        case ETIMEDOUT:
@@ -320,7 +320,7 @@
          /* It could be the host is down, or it could be firewalled.  We
             will go on the safe side & assume port is closed ... on second
             thought, lets go firewalled! and see if it causes any trouble */
-         posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_FIREWALLED, pil, csi);
+         posportupdate(target, current, trynum, scan, ss, CONNECT_SCAN, PORT_FIREWALLED, pil, csi, 0, 0);
          break;
        case ENETDOWN:
        case ENETUNREACH:
@@ -363,6 +363,8 @@
   struct timeval tv;
   struct timeval start;
   int quit = 0;
+  int icmpresp = 0;
+  in_addr_t intermediateip = 0;
 
   gettimeofday(&start, NULL);
 
@@ -434,8 +436,10 @@
       }
       if (scantype == SYN_SCAN) {
        if (tcp->th_flags & TH_RST) {
+         intermediateip = icmpresp = 0;
          newstate = PORT_CLOSED;
        } else if ((tcp->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
+         intermediateip = icmpresp = 0;
          newstate = PORT_OPEN;
        } else {
          if (o.debugging)
@@ -445,6 +449,7 @@
       }
       else if (scantype == WINDOW_SCAN) {
        if (tcp->th_flags & TH_RST) {
+         intermediateip = icmpresp = 0;
          if (tcp->th_win) {
            newstate = PORT_OPEN;
          } else {
@@ -458,6 +463,7 @@
       }
       else if (scantype == ACK_SCAN) {
        if (tcp->th_flags & TH_RST) {     
+         intermediateip = icmpresp = 0;
          newstate = PORT_UNFIREWALLED;
        } else {
          if (o.debugging)
@@ -489,6 +495,21 @@
       }
 
       data = (u16 *) ((char *)ip2 + 4 * ip2->ip_hl);
+      intermediateip = 0;
+      icmpresp = icmp->icmp_type * 256 + icmp->icmp_code;
+      /* Wasn't it sent from the host itself? */
+      if (ip->ip_src.s_addr != ip2->ip_dst.s_addr) {
+        intermediateip = ip->ip_src.s_addr;
+        target->intermediateresp++;
+        if (o.debugging || o.verbose) {
+          log_write(LOG_STDOUT, "ICMP %d/%d from intermediate router %s regarding ", icmp->icmp_type, icmp->icmp_code,
+            inet_ntoa(inet_makeaddr(htonl(ip->ip_src.s_addr),0)));
+          log_write(LOG_STDOUT, "%s port %d\n", inet_ntoa(inet_makeaddr(htonl(ip2->ip_dst.s_addr),0)), ntohs(data[1]));
+        }
+      } else {
+        target->icmpresponse++;
+      }
+
       /*           log_write(LOG_STDOUT, "Caught ICMP packet:\n");
                    hdump(icmp, ntohs(ip->ip_len) - sizeof(struct ip)); */
       if (icmp->icmp_type == 3) {
@@ -519,7 +540,7 @@
     /* OK, now we manipulate the port lists and adjust the time */
     if (current) {
       posportupdate(target, current, trynum, scan, ss, SYN_SCAN, newstate,
-                   pil, NULL);
+                   pil, NULL, intermediateip, icmpresp);
       current = NULL;
       trynum = -1;
       newstate = PORT_UNKNOWN;
@@ -871,7 +892,7 @@
                  current->sd[current->trynum] = res;           
                  res =  connect(res,(struct sockaddr *)&sock, socklen);
                  if (res != -1) {
-                   posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_OPEN, &pil, &csi);
+                   posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_OPEN, &pil, &csi, 0, 0);
                  } else {
                    switch(errno) {
                    case EINPROGRESS: /* The one I always see */
@@ -891,7 +912,7 @@
                        perror(""); /*falling through intentionally*/
                      }
                    case ECONNREFUSED:
-                     posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_CLOSED, &pil, &csi);
+                     posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_CLOSED, &pil, &csi, 0, 
0);
                      break;
                    }             
                  }
@@ -950,7 +971,7 @@
              current->sd[current->trynum] = res;               
              res =  connect(res,(struct sockaddr *)&sock, socklen);
              if (res != -1) {
-               posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_OPEN, &pil, &csi);
+               posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_OPEN, &pil, &csi, 0, 0);
              } else {
                switch(errno) {
                case EINPROGRESS: /* The one I always see */
@@ -970,7 +991,7 @@
                    perror(""); /*falling through intentionally*/
                  }
                case ECONNREFUSED:
-                 posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_CLOSED, &pil, &csi);
+                 posportupdate(target, current, current->trynum, scan, &ss, scantype, PORT_CLOSED, &pil, &csi, 0, 0);
                  break;
                }                 
              }     
@@ -1058,7 +1079,7 @@
        /* Consider the ports firewalled */     
        for( current = pil.firewalled; current ; 
             current = (current->next > -1)? &scan[current->next] : NULL) {
-         addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_FIREWALLED);
+         addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_FIREWALLED, 0, 0);
        }
        pil.testinglist = NULL;
       }
@@ -1188,7 +1209,7 @@
                res = recvtime(sd, recvbuf, 2048,10);
              }
              if (recvbuf[0] == '1' || recvbuf[0] == '2') {
-               addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_OPEN);
+               addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_OPEN, 0, 0);
                if (recvbuf[0] == '1') {
                  res = recvtime(sd, recvbuf, 2048,5);
                  recvbuf[res] = '\0';
@@ -1204,7 +1225,7 @@
                }
              } else {
                /* This means the port is closed ... */
-               addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_CLOSED);
+               addport(&target->ports, portarray[i], IPPROTO_TCP, NULL, PORT_CLOSED, 0, 0);
              }
            }
          }
@@ -1253,6 +1274,8 @@
   int packcount, timedout;
   int UDPPacketWarning = 0;
   int i;
+  int icmpresp = 0;
+  in_addr_t intermediateip = 0;
   u16 *data;
   int packet_trynum = 0;
   int windowdecrease = 0; /* Has the window been decreased this round yet? */
@@ -1464,6 +1487,7 @@
              if (ip->ip_p == IPPROTO_TCP) {
                tcp = (struct tcphdr *) (((char *) ip) + 4 * ip->ip_hl);
                if (tcp->th_flags & TH_RST) {       
+                 intermediateip = icmpresp = 0;
                  newstate = PORT_CLOSED;
                  newport = ntohs(tcp->th_sport);
                  if (portlookup[newport] < 0) {
@@ -1499,12 +1523,27 @@
              } else if (ip->ip_p == IPPROTO_ICMP) {
                icmp = (struct icmp *) ((char *)ip + 4 * ip->ip_hl);
                ip2 = (struct ip *) (((char *) icmp) + 8);
+               intermediateip = 0;
                if (ip2->ip_dst.s_addr != target->v4host().s_addr)
                  continue;
                data = (u16 *) ((char *)ip2 + 4 * ip2->ip_hl);
                /*          log_write(LOG_STDOUT, "Caught ICMP packet:\n");
                            hdump(icmp, ntohs(ip->ip_len) - sizeof(struct ip)); */
 
+               icmpresp = icmp->icmp_type * 256 + icmp->icmp_code;
+               /* Wasn't it sent from the host itself? */
+               if (ip->ip_src.s_addr != ip2->ip_dst.s_addr) {
+                 intermediateip = ip->ip_src.s_addr;
+                 target->intermediateresp++;
+                 if (o.debugging || o.verbose) {
+                   log_write(LOG_STDOUT, "ICMP %d/%d from intermediate router %s regarding ", icmp->icmp_type, 
icmp->icmp_code,
+                             inet_ntoa(inet_makeaddr(htonl(ip->ip_src.s_addr),0)));
+                   log_write(LOG_STDOUT, "%s port %d\n", inet_ntoa(inet_makeaddr(htonl(ip2->ip_dst.s_addr),0)), 
ntohs(data[1]));
+                 }
+               } else {
+                 target->icmpresponse++;
+               }
+
                if (icmp->icmp_type == 3) {
                  if (scantype != IPPROT_SCAN)
                    newport = ntohs(data[1]);
@@ -1530,10 +1569,16 @@
                
                  switch(icmp->icmp_code) {
                  
+                 case 0: /* Network unreachable */
                  case 1: /* Host unreachable */
+                     newstate = PORT_FIREWALLED;
+                   break;
+                 
                  case 2: /* pr0t0c0l unreachable */
-                   if (scantype == IPPROT_SCAN) {
+                   if (scantype == IPPROT_SCAN &&
+                       ip->ip_src.s_addr == target->v4host().s_addr) {
                      newstate = PORT_CLOSED;
+                     icmpresp = 0;
                    } else
                      newstate = PORT_FIREWALLED;
                    break;
@@ -1542,12 +1587,22 @@
                    if (scantype == UDP_SCAN && 
                        ip->ip_src.s_addr == target->v4host().s_addr) {
                      newstate = PORT_CLOSED;
+                     icmpresp = 0;
                    } else newstate = PORT_FIREWALLED;
                    break;
                  
-                 case 9:
-                 case 10:
+                   //            case 4: /* Fragmentation Needed/DF set */
+                   //            case 5: /* Source Route failed */
+                 case 6: /* Network unknown */
+                 case 7: /* Host unknown */
+                 case 8: /* Host isolated */
+                 case 9: /* Net anonymous */
+                 case 10: /* Host anonymous */
+                   //            case 11: /* Net unreachable for TOS */
+                   //            case 12: /* Host unreachable for TOS */
                  case 13: /* Administratively prohibited packet */
+                   //            case 14: /* Precedence violation */
+                   //            case 15: /* Precedence cutoff */
                    newstate = PORT_FIREWALLED;
                    break;              
                  
@@ -1625,8 +1680,8 @@
                current->state = newstate;
                addport(&target->ports, current->portno, 
                        (scantype == UDP_SCAN)? IPPROTO_UDP :
-                         (scantype == IPPROT_SCAN? IPPROTO_IP: IPPROTO_TCP), 
-                       NULL, current->state);
+                       (scantype == IPPROT_SCAN? IPPROTO_IP: IPPROTO_TCP), 
+                       NULL, current->state, intermediateip, icmpresp);
              }
            }
          }
@@ -1662,11 +1717,11 @@
   
   for (current = openlist; current;  current = (current->next >= 0)? &scan[current->next] : NULL) {
     if (scantype == IPPROT_SCAN)
-      addport(&target->ports, current->portno, IPPROTO_IP, NULL, PORT_OPEN);
+      addport(&target->ports, current->portno, IPPROTO_IP, NULL, PORT_OPEN, 0, 0);
     else if (scantype != UDP_SCAN)
-      addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_OPEN);
+      addport(&target->ports, current->portno, IPPROTO_TCP, NULL, PORT_OPEN, 0, 0);
     else
-      addport(&target->ports, current->portno, IPPROTO_UDP, NULL, PORT_OPEN);
+      addport(&target->ports, current->portno, IPPROTO_UDP, NULL, PORT_OPEN, 0, 0);
   }
 
  superscan_timedout:
diff -ruBN nmap-3.10ALPHA7/targets.cc nmap-3.10ALPHA7-aware/targets.cc
--- nmap-3.10ALPHA7/targets.cc  Wed Dec 18 07:10:07 2002
+++ nmap-3.10ALPHA7-aware/targets.cc    Thu Dec 19 10:04:18 2002
@@ -1134,7 +1134,7 @@
         of the ports the user ASKED for */
       if (ports && ports->tcp_count == 1 && ports->tcp_ports[0] == newport)
        addport(&(hostbatch[hostnum]->ports), newport, IPPROTO_TCP, NULL, 
-               newportstate);
+               newportstate, 0, 0);
     }
 }
 return 0;

---------------------------------------------------------------------
For help using this (nmap-dev) mailing list, send a blank email to 
nmap-dev-help () insecure org . List run by ezmlm-idx (www.ezmlm.org).

Current thread: