Index: global_structures.h
===================================================================
--- global_structures.h	(revision 22957)
+++ global_structures.h	(working copy)
@@ -244,6 +244,6 @@
 	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, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_PRE_SCAN, SCRIPT_SCAN, SCRIPT_POST_SCAN, TRACEROUTE}stype;
+typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_PRE_SCAN, SCRIPT_PORTSCAN, SCRIPT_SCAN, SCRIPT_POST_SCAN, TRACEROUTE}stype;
 
 #endif /*GLOBAL_STRUCTURES_H */
Index: nse_main.cc
===================================================================
--- nse_main.cc	(revision 22957)
+++ nse_main.cc	(working copy)
@@ -24,6 +24,7 @@
 
 /* Script Scan phases */
 #define NSE_PRE_SCAN  "NSE_PRE_SCAN"
+#define NSE_PORTSCAN  "NSE_PORTSCAN"
 #define NSE_SCAN      "NSE_SCAN"
 #define NSE_POST_SCAN "NSE_POST_SCAN"
 
@@ -455,6 +456,9 @@
     case SCRIPT_PRE_SCAN:
       lua_pushstring(L, NSE_PRE_SCAN);
       break;
+    case SCRIPT_PORTSCAN:
+      lua_pushstring(L, NSE_PORTSCAN);
+      break;
     case SCRIPT_SCAN:
       lua_pushstring(L, NSE_SCAN);
       break;
Index: NmapOps.h
===================================================================
--- NmapOps.h	(revision 22957)
+++ NmapOps.h	(working copy)
@@ -326,6 +326,7 @@
   int scripttrace;
   int scriptupdatedb;
   bool scripthelp;
+  bool scriptportscan;
   void chooseScripts(char* argument);
   std::vector<std::string> chosenScripts;
 #endif
Index: nse_nmaplib.cc
===================================================================
--- nse_nmaplib.cc	(revision 22957)
+++ nse_nmaplib.cc	(working copy)
@@ -382,9 +382,9 @@
  */
 static int l_get_ports (lua_State *L)
 {
-  static const char *state_op[] = {"open", "filtered", "unfiltered", "closed",
+  static const char *state_op[] = {"unknown", "open", "filtered", "unfiltered", "closed",
       "open|filtered", "closed|filtered", NULL};
-  static const int states[] = {PORT_OPEN, PORT_FILTERED, PORT_UNFILTERED,
+  static const int states[] = {PORT_UNKNOWN, PORT_OPEN, PORT_FILTERED, PORT_UNFILTERED,
       PORT_CLOSED, PORT_OPENFILTERED, PORT_CLOSEDFILTERED};
   Port *p = NULL;
   Port port; /* dummy Port for nextPort */
@@ -450,8 +450,8 @@
  * */
 static int l_set_port_state (lua_State *L)
 {
-  static const int opstate[] = {PORT_OPEN, PORT_CLOSED};
-  static const char *op[] = {"open", "closed", NULL};
+  static const int opstate[] = {PORT_OPEN, PORT_CLOSED, PORT_FILTERED};
+  static const char *op[] = {"open", "closed", "filtered", NULL};
   Target *target;
   Port *p;
   Port port;
@@ -470,6 +470,11 @@
           return 0;
         target->ports.setPortState(p->portno, p->proto, PORT_CLOSED);
         break;
+      case PORT_FILTERED:
+        if (p->state == PORT_FILTERED)
+          return 0;
+        target->ports.setPortState(p->portno, p->proto, PORT_FILTERED);
+        break;
     }
     target->ports.setStateReason(p->portno, p->proto, ER_SCRIPT, 0, 0);
   }
Index: nmap.cc
===================================================================
--- nmap.cc	(revision 22957)
+++ nmap.cc	(working copy)
@@ -1181,6 +1181,7 @@
         case 'B':  fatal("No scan type 'B', did you mean bounce scan (-b)?"); break;
 #ifndef NOLUA
         case 'C':  o.script = 1; break;
+        case 'K':  o.scriptportscan = true; break;
 #endif
         case 'F':  o.finscan = 1; break;
         case 'L':  o.listscan = 1; o.noportscan = 1; o.pingtype = PINGTYPE_NONE; break;
@@ -1637,7 +1638,7 @@
   }
   if (o.servicescan)
     o.scriptversion = 1;
-  if (o.scriptversion || o.script || o.scriptupdatedb)
+  if (o.scriptversion || o.script || o.scriptupdatedb || o.scriptportscan)
     open_nse();
 
   /* Run the script pre-scanning phase */
@@ -1711,7 +1712,7 @@
     
       if ((o.noportscan && !o.traceroute
 #ifndef NOLUA
-      && !o.script
+      && !o.script && !o.scriptportscan
 #endif
           ) || o.listscan) {
         /* We're done with the hosts */
@@ -1836,6 +1837,12 @@
       
       if (o.ipprotscan)
         ultra_scan(Targets, &ports, IPPROT_SCAN);
+
+#ifndef NOLUA
+      if(o.scriptportscan) {
+        script_scan(Targets, SCRIPT_PORTSCAN);
+      }
+#endif
       
       /* These lame functions can only handle one target at a time */
       if (o.idlescan) {
@@ -2597,6 +2604,7 @@
   case SERVICE_SCAN: return "Service Scan"; break;
   case OS_SCAN: return "OS Scan"; break;
   case SCRIPT_PRE_SCAN: return "Script Pre-Scan"; break;
+  case SCRIPT_PORTSCAN: return "Script port Scan"; break;
   case SCRIPT_SCAN: return "Script Scan"; break;
   case SCRIPT_POST_SCAN: return "Script Post-Scan"; break;
   case TRACEROUTE: return "Traceroute" ; break;
Index: NmapOps.cc
===================================================================
--- NmapOps.cc	(revision 22957)
+++ NmapOps.cc	(working copy)
@@ -296,6 +296,7 @@
   scripttrace = 0;
   scriptupdatedb = 0;
   scripthelp = false;
+  scriptportscan = false;
   chosenScripts.clear();
 #endif
   memset(&sourcesock, 0, sizeof(sourcesock));
@@ -307,7 +308,11 @@
 }
 
 bool NmapOps::TCPScan() {
-  return ackscan|bouncescan|connectscan|finscan|idlescan|maimonscan|nullscan|synscan|windowscan|xmasscan;
+  return ackscan|bouncescan|connectscan|finscan|idlescan|maimonscan|nullscan|synscan|windowscan|xmasscan
+#ifndef NOLUA
+    |scriptportscan
+#endif
+    ;
 }
 
 bool NmapOps::UDPScan() {
@@ -315,7 +320,11 @@
 }
 
 bool NmapOps::RawScan() {
-  if (ackscan||finscan||idlescan||ipprotscan||maimonscan||nullscan||osscan||synscan||udpscan||windowscan||xmasscan||sctpinitscan||sctpcookieechoscan||traceroute)
+  if (ackscan||finscan||idlescan||ipprotscan||maimonscan||nullscan||osscan||synscan||udpscan||windowscan||xmasscan||sctpinitscan||sctpcookieechoscan||traceroute
+#ifndef NOLUA
+      ||scriptportscan
+#endif
+      )
     return true;
   if (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS|PINGTYPE_TCP_USE_ACK|PINGTYPE_UDP|PINGTYPE_SCTP_INIT))
     return true;
Index: nse_main.lua
===================================================================
--- nse_main.lua	(revision 22957)
+++ nse_main.lua	(working copy)
@@ -34,6 +34,7 @@
 
 -- Script Scan phases.
 local NSE_PRE_SCAN  = "NSE_PRE_SCAN";
+local NSE_PORTSCAN  = "NSE_PORTSCAN";
 local NSE_SCAN      = "NSE_SCAN";
 local NSE_POST_SCAN = "NSE_POST_SCAN";
 
@@ -52,6 +53,7 @@
 -- Table of different supported rules.
 local NSE_SCRIPT_RULES = {
   prerule = "prerule",
+  scanrule = "scanrule",
   hostrule = "hostrule",
   portrule = "portrule",
   postrule = "postrule",
@@ -402,6 +404,7 @@
     end
     assert(next(rules), filename.." is missing required function: 'rule'");
     local prerule = rules.prerule;
+    local scanrule = rules.scanrule;
     local hostrule = rules.hostrule;
     local portrule = rules.portrule;
     local postrule = rules.postrule;
@@ -423,6 +426,7 @@
       id = match(filename, "^.-[/\\]([^\\/]-)%.nse$") or short_basename,
       file_closure = file_closure,
       prerule = prerule,
+      scanrule = scanrule,
       hostrule = hostrule,
       portrule = portrule,
       postrule = postrule,
@@ -730,6 +734,12 @@
 
   if (scantype == NSE_PRE_SCAN) then
     print_verbose(1, "Script Pre-scanning.");
+  elseif (scantype == NSE_PORTSCAN) then
+    if #hosts > 1 then
+      print_verbose(1, "NSE ports scanning %d hosts.", #hosts);
+    elseif #hosts == 1 then
+      print_verbose(1, "NSE ports scanning %s.", hosts[1].ip);
+    end
   elseif (scantype == NSE_SCAN) then
     if #hosts > 1 then
       print_verbose(1, "Script scanning %d hosts.", #hosts);
@@ -1072,6 +1082,17 @@
              yield(thread);
            end
         end
+      -- activate scanrule scripts
+      elseif (scantype == NSE_PORTSCAN) then
+        for j, host in ipairs(hosts) do
+          for _, script in ipairs(scripts) do
+            local thread = script:new_thread("scanrule", tcopy(host));
+            if thread then
+              thread.args, thread.host = {n = 1, tcopy(host)}, host;
+              yield(thread);
+            end
+          end
+        end
       -- activate hostrule and portrule scripts
       elseif (scantype == NSE_SCAN) then
         -- Check hostrules for this host.
