--- global_structures.h~	Fri Sep 10 18:58:50 1999
+++ global_structures.h	Fri Sep 10 19:09:43 1999
@@ -169,6 +169,7 @@
   int xmasscan;
   int fragscan;
   int synscan;
+  int ackscan;
   int maimonscan;
   int finscan;
   int udpscan;
@@ -180,7 +181,7 @@
 };
   
 typedef port *portlist;
-typedef enum { SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, RPC_SCAN, MAIMON_SCAN } stype;
+typedef enum { SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, ACK_SCAN, RPC_SCAN, MAIMON_SCAN } stype;
 
 #endif /*GLOBAL_STRUCTURES_H */
 
--- nmap.c~	Fri Sep 10 18:47:27 1999
+++ nmap.c	Fri Sep 10 19:09:44 1999
@@ -253,6 +253,7 @@
 	case 'P':  o.pingscan = 1; break;
 	case 'R':  o.rpcscan = 1; break;
 	case 'S':  o.synscan = 1; break;	  
+	case 'A':  o.ackscan = 1; break;
 	case 'T':  o.connectscan = 1; break;
 	case 'U':  
 	  fprintf(o.nmap_stdout, "WARNING:  -sU is now UDP scan -- for TCP FIN scan use -sF\n");
@@ -283,7 +284,7 @@
 
 /* Now we check the option sanity */
 /* Insure that at least one scantype is selected */
-if (!o.connectscan && !o.udpscan && !o.synscan && !o.finscan && !o.maimonscan &&  !o.nullscan && !o.xmasscan && !o.bouncescan && !o.pingscan) {
+if (!o.connectscan && !o.udpscan && !o.synscan && !o.ackscan && !o.finscan && !o.maimonscan &&  !o.nullscan && !o.xmasscan && !o.bouncescan && !o.pingscan) {
   o.connectscan++;
   if (o.verbose) error("No tcp,udp, or ICMP scantype specified, assuming vanilla tcp connect() scan. Use -sP if you really don't want to portscan (and just want to see what hosts are up).");
 }
@@ -299,7 +300,7 @@
 if (fastscan && ports) {
   fatal("You can specify fast scan (-F) or explicitly select individual ports (-p), but not both");
 } else if (fastscan) {
-  ports = getfastports(o.synscan|o.connectscan|o.fragscan|o.finscan|o.maimonscan|o.bouncescan|o.nullscan|o.xmasscan,o.udpscan);
+  ports = getfastports(o.ackscan|o.synscan|o.connectscan|o.fragscan|o.finscan|o.maimonscan|o.bouncescan|o.nullscan|o.xmasscan,o.udpscan);
 }
 
 if (o.pingscan && ports) {
@@ -311,7 +312,7 @@
 }
 
 if (!ports) {
-  ports = getdefaultports(o.synscan|o.connectscan|o.fragscan|o.finscan|
+  ports = getdefaultports(o.ackscan|o.synscan|o.connectscan|o.fragscan|o.finscan|
 			  o.maimonscan|o.bouncescan|o.nullscan|o.xmasscan,
 			  o.udpscan);
 }
@@ -320,7 +321,7 @@
 if (!o.tcp_probe_port) o.tcp_probe_port = 80;
 
 
-if (o.pingscan && (o.connectscan || o.udpscan || o.synscan || o.finscan || o.maimonscan ||  o.nullscan || o.xmasscan || o.bouncescan)) {
+if (o.pingscan && (o.connectscan || o.udpscan || o.ackscan || o.synscan || o.finscan || o.maimonscan ||  o.nullscan || o.xmasscan || o.bouncescan)) {
   fatal("Ping scan is not valid with any other scan types (the other ones all include a ping scan");
 }
 
@@ -332,7 +333,7 @@
     o.pingtype = PINGTYPE_TCP;
   }
 
-  if (o.finscan || o.synscan || o.maimonscan || o.nullscan || o.xmasscan 
+  if (o.finscan || o.ackscan || o.synscan || o.maimonscan || o.nullscan || o.xmasscan 
       || o.udpscan ) {
     fatal("You requested a scan type which requires r00t privileges, and you do not have them.\n");
   }
@@ -353,8 +354,8 @@
 if (o.bouncescan && o.pingtype != PINGTYPE_NONE) 
   fprintf(o.nmap_stdout, "Hint: if your bounce scan target hosts aren't reachable from here, remember to use -P0 so we don't try and ping them prior to the scan\n");
 
-if (o.connectscan + o.synscan + o.finscan + o.maimonscan + o.xmasscan + o.nullscan > 1) {
-  fatal("You specified more than one type of TCP scan.  Please choose only one of -sT, -sS, -sF, -sM, -sX, and -sN");
+if (o.connectscan + o.ackscan + o.synscan + o.finscan + o.maimonscan + o.xmasscan + o.nullscan > 1) {
+  fatal("You specified more than one type of TCP scan.  Please choose only one of -sT, -sS, -sF, -sM, -sX, -sA, and -sN");
 }
 
 if (o.numdecoys > 0 && (o.bouncescan || o.connectscan)) {
@@ -362,9 +363,9 @@
 }
 
 if (o.fragscan && (o.connectscan || 
-		   (o.udpscan && (o.synscan + o.finscan + o.maimonscan + 
+		   (o.udpscan && (o.ackscan + o.synscan + o.finscan + o.maimonscan + 
 				  o.xmasscan + o.nullscan == 0))))
-  fatal("Fragmentation scan can only be used with SYN, FIN, Maimon, XMAS, or NULL scan types");
+  fatal("Fragmentation scan can only be used with SYN, FIN, Maimon, XMAS, ACK, or NULL scan types");
  
 if (o.identscan && !o.connectscan) {
   error("Identscan only works with connect scan (-sT) ... ignoring option");
@@ -533,7 +534,7 @@
  if (currenths->flags & HOST_UP /* && !currenths->wierd_responses*/ &&
      !o.pingscan) {
    
-   if (currenths->flags & HOST_UP && !currenths->source_ip.s_addr && ( o.synscan || o.finscan || o.maimonscan || o.udpscan || o.nullscan || o.xmasscan)) {
+   if (currenths->flags & HOST_UP && !currenths->source_ip.s_addr && ( o.ackscan || o.synscan || o.finscan || o.maimonscan || o.udpscan || o.nullscan || o.xmasscan)) {
      if (gethostname(myname, MAXHOSTNAMELEN) || 
 	 !(target = gethostbyname(myname)))
        fatal("Cannot get hostname!  Try using -S <my_IP_address> or -e <interface to scan through>\n"); 
@@ -545,7 +546,7 @@
    }
    
    /* Figure out what link-layer device (interface) to use (ie eth0, ppp0, etc) */
-   if (!*currenths->device && currenths->flags & HOST_UP && (o.nullscan || o.xmasscan || o.udpscan || o.finscan || o.maimonscan ||  o.synscan || o.osscan) && (ipaddr2devname( currenths->device, &currenths->source_ip) != 0))
+   if (!*currenths->device && currenths->flags & HOST_UP && (o.nullscan || o.xmasscan || o.udpscan || o.finscan || o.maimonscan ||  o.synscan || o.osscan || o.ackscan) && (ipaddr2devname( currenths->device, &currenths->source_ip) != 0))
      fatal("Could not figure out what device to send the packet out on!  You might possibly want to try -S (but this is probably a bigger problem).  If you are trying to sp00f the source of a SYN/FIN scan with -S <fakeip>, then you must use -e eth0 (or other devicename) to tell us what interface to use.\n");
    /* Set up the decoy */
    o.decoys[o.decoyturn] = currenths->source_ip;
@@ -554,6 +555,7 @@
    
    
    if (o.synscan) pos_scan(currenths, ports, SYN_SCAN);
+   if (o.ackscan) pos_scan(currenths, ports, ACK_SCAN);
    if (o.connectscan) pos_scan(currenths, ports, CONNECT_SCAN);      
    
    if (o.finscan) super_scan(currenths, ports, FIN_SCAN);
@@ -1993,7 +1995,7 @@
   FD_ZERO(&csi.fds_write);
   FD_ZERO(&csi.fds_except);
 
-  if (scantype == SYN_SCAN || scantype == RPC_SCAN)
+  if (scantype == SYN_SCAN || scantype == RPC_SCAN || scantype == ACK_SCAN)
     ss.max_width = 150;
   else ss.max_width = o.max_sockets;
 
@@ -2025,7 +2027,7 @@
   }
    
   /* Init our raw socket */
-  if (scantype == SYN_SCAN) {  
+  if ((scantype == SYN_SCAN) || (scantype == ACK_SCAN)) {  
     if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
       pfatal("socket troubles in super_scan");
     /* We do not wan't to unblock the socket since we want to wait 
@@ -2075,7 +2077,10 @@
       fatal("Error compiling our pcap filter: %s\n", pcap_geterr(pd));
     if (pcap_setfilter(pd, &fcode) < 0 )
       fatal("Failed to set the pcap filter: %s\n", pcap_geterr(pd));
-    scanflags = TH_SYN;
+    if (scantype == SYN_SCAN)
+      scanflags = TH_SYN;
+    else
+      scanflags = TH_ACK;
   } else if (scantype == CONNECT_SCAN) {
     rawsd = -1;
     /* Init our sock */
@@ -2107,7 +2112,9 @@
       fprintf(o.nmap_stdout, "Initiating SYN half-open stealth scan against %s (%s)\n", target->name, inet_ntoa(target->host));
     else if (scantype == CONNECT_SCAN)
       fprintf(o.nmap_stdout, "Initiating TCP connect() scan against %s (%s)\n",target->name, inet_ntoa(target->host)); 
-    else  {
+    else if (scantype == ACK_SCAN)
+      fprintf(o.nmap_stdout, "Initiating ACK scan against %s (%s)\n",target->name, inet_ntoa(target->host));
+    else {
       fprintf(o.nmap_stdout, "Initiating RPC scan against %s (%s)\n",target->name, inet_ntoa(target->host)); 
     }
   }
@@ -2181,7 +2188,7 @@
 		  scan[current->next].prev = current - scan;	      
 		}
 	      }
-	      if (scantype == SYN_SCAN || scantype == RPC_SCAN)
+	      if (scantype == SYN_SCAN || scantype == RPC_SCAN || scantype == ACK_SCAN)
 		ss.numqueries_outstanding--;
 	      else {
 		/* close the appropriate sd for each try */
@@ -2202,7 +2209,7 @@
 	      current->trynum++;
 	      gettimeofday(&current->sent[current->trynum], NULL);
 	      now = current->sent[current->trynum];
-	      if (scantype == SYN_SCAN) {	      
+	      if ((scantype == SYN_SCAN) || (scantype == ACK_SCAN)) {	      
 		for(decoy=0; decoy < o.numdecoys; decoy++) {
 		  if (o.fragscan)
 		    send_small_fragz(rawsd, &o.decoys[decoy], &target->host, sequences[current->trynum],o.magic_port + tries * 3 + current->trynum, current->portno, scanflags);
@@ -2292,7 +2299,7 @@
 	  /*	if (!testinglist) testinglist = current; */
 	  ss.numqueries_outstanding++;
 	  gettimeofday(&current->sent[0], NULL);
-	  if (scantype == SYN_SCAN) {	  
+	  if ((scantype == SYN_SCAN) || (scantype == ACK_SCAN)) {	  
 	    for(decoy=0; decoy < o.numdecoys; decoy++) {
 	      if (o.fragscan)
 		send_small_fragz(rawsd, &o.decoys[decoy], &target->host, sequences[current->trynum], o.magic_port + tries * 3, current->portno, scanflags);
@@ -2349,8 +2356,8 @@
 
       /* Now that we have sent the packets we wait for responses */
       ss.alreadydecreasedqueries = 0;
-      if (scantype == SYN_SCAN)
-	get_syn_results(target, scan, &ss, &pil, portlookup, pd, sequences);
+      if ((scantype == SYN_SCAN) || (scantype == ACK_SCAN))
+	get_syn_results(target, scan, &ss, &pil, portlookup, pd, sequences, scantype);
       else if (scantype == RPC_SCAN) {
       /* We only bother worrying about responses if we haven't reached
          a conclusion yet */
@@ -2435,7 +2442,7 @@
   }
 
   if (o.verbose)
-    fprintf(o.nmap_stdout, "The %s scan took %ld seconds to scan %d ports.\n", (scantype == SYN_SCAN)? "SYN" : (scantype == CONNECT_SCAN)? "TCP connect" : "RPC",  (long) time(NULL) - starttime, o.numports);
+    fprintf(o.nmap_stdout, "The %s scan took %ld seconds to scan %d ports.\n", (scantype == ACK_SCAN) ? "ACK" : (scantype == SYN_SCAN)? "SYN" : (scantype == CONNECT_SCAN)? "TCP connect" : "RPC",  (long) time(NULL) - starttime, o.numports);
   
   free(scan);
   if (rawsd >= 0) 
@@ -2857,7 +2864,7 @@
 
 void get_syn_results(struct hoststruct *target, struct portinfo *scan,
 		     struct scanstats *ss, struct portinfolist *pil, 
-		     int *portlookup, pcap_t *pd, unsigned long *sequences) {
+		     int *portlookup, pcap_t *pd, unsigned long *sequences, stype scantype) {
 
 struct ip *ip;
 int bytes;
@@ -2916,12 +2923,21 @@
 	      error("Received SYN packet implying trynum %d from port %hi even though that port is only on trynum %d (could be from an earlier round)", trynum, newport, current->trynum);
 	    trynum = -1;
 	  }
-	  if ((tcp->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {	  
-	    newstate = PORT_OPEN;
-	  }
-	  else if (tcp->th_flags & TH_RST) {	  
-	    newstate = PORT_CLOSED;
+          if (scantype == SYN_SCAN) {
+	    if ((tcp->th_flags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {	  
+	      newstate = PORT_OPEN;
+	    }
+            else if (tcp->th_flags & TH_RST) {	  
+	      newstate = PORT_CLOSED;
 	    }	
+          }
+          if (scantype == ACK_SCAN) {
+            if (tcp->th_win) {
+              newstate = PORT_OPEN;
+            } else {
+              newstate = PORT_CLOSED;
+            }
+          } 
 	} else if (ip->ip_p == IPPROTO_ICMP) {
 	  icmp = (struct icmp *) ((char *)ip + sizeof(struct ip));
 	  ip2 = (struct ip *) (((char *) ip) + 4 * ip->ip_hl + 8);
@@ -2990,8 +3006,8 @@
 		fatal("Deletion of port %d failed\n", ports[i]);
 	  }
 	}
-	if (o.connectscan || o.nullscan || o.xmasscan || o.synscan || 
-	    o.maimonscan || o.finscan || o.bouncescan) {
+	if (o.connectscan || o.nullscan || o.xmasscan || o.synscan ||
+            o.ackscan || o.maimonscan || o.finscan || o.bouncescan) {
 	  current = lookupport(*pl, ports[i], IPPROTO_TCP);
 	  if (!current)
 	    addport(pl, ports[i], IPPROTO_TCP, NULL, PORT_UNFIREWALLED);
--- nmap.h~	Fri Sep 10 19:02:15 1999
+++ nmap.h	Fri Sep 10 19:09:45 1999
@@ -258,7 +258,7 @@
 		   struct portinfolist *pil, struct connectsockinfo *csi);
 void get_syn_results(struct hoststruct *target, struct portinfo *scan,
 		     struct scanstats *ss, struct portinfolist *pil, 
-		     int *portlookup, pcap_t *pd, unsigned long *sequences);
+		     int *portlookup, pcap_t *pd, unsigned long *sequences, stype scantype);
 int get_connect_results(struct hoststruct *target, struct portinfo *scan, 
 			 struct scanstats *ss, struct portinfolist *pil, 
 			 int *portlookup, unsigned long *sequences, 
