From 144b8f9c58da2836728235ba2cea82c6ccbcffea Mon Sep 17 00:00:00 2001
From: Přemysl Janouch 
Date: Wed, 13 May 2015 05:56:31 +0200
Subject: Print undetermined services
---
 ponymap.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 69 insertions(+), 7 deletions(-)
diff --git a/ponymap.c b/ponymap.c
index bd7dcff..54f9df3 100644
--- a/ponymap.c
+++ b/ponymap.c
@@ -197,9 +197,10 @@ struct target
 	char ip_string[INET_ADDRSTRLEN];    ///< IP address as a string
 	char *hostname;                     ///< Hostname
 
-	/// All units that have ended, successfully finding a service.  These don't
-	/// hold a reference to us as they're considered a part of this object;
-	/// we hold a reference to them.
+	/// All units that have ended, either successfully finding a service, or
+	/// just successful in establishing a connection.
+	/// These don't hold a reference to us as they're considered a part of
+	/// this object; we hold a reference to them.
 	struct unit *results;
 
 	/// All currently running units for this target, holding a reference to us.
@@ -554,10 +555,12 @@ unit_abort (struct unit *u)
 	// the generator right now, though, as we could spin in a long loop
 	poller_idle_set (&u->target->ctx->step_event);
 
-	if (u->success)
+	// If the scan has been started, we have successfully connected at least
+	if (u->scan_started || u->success)
 	{
 		struct target *target = u->target;
-		target->ctx->stats_results++;
+		if (u->success)
+			target->ctx->stats_results++;
 
 		// Now we're a part of the target
 		LIST_PREPEND (target->results, u);
@@ -1314,6 +1317,7 @@ struct target_dump_data
 {
 	struct unit **results;              ///< Results sorted by service
 	size_t results_len;                 ///< Number of results
+	uint32_t *undetermined;             ///< Bitmap of undetermined services
 };
 
 static void
@@ -1362,6 +1366,24 @@ target_dump_json (struct target *self, struct target_dump_data *data)
 		for (size_t k = 0; k < u->info.len; k++)
 			json_array_append_new (info, json_string (u->info.vector[k]));
 	}
+
+	json_t *undetermined = json_array ();
+	json_object_set_new (o, "undetermined", undetermined);
+
+	if (!data->undetermined)
+		return;
+
+	size_t block = 8 * sizeof *data->undetermined;
+	for (size_t i = 0; i < 65536 / block; i++)
+		for (size_t k = 0; k < block; k++)
+		{
+			if (!(data->undetermined[i] & (1 << k)))
+				continue;
+
+			service = json_object ();
+			json_object_set_new (service, "port", json_integer (i * block + k));
+			json_array_append_new (undetermined, service);
+		}
 }
 
 static void
@@ -1408,6 +1430,24 @@ target_dump_terminal (struct target *self, struct target_dump_data *data)
 		}
 	}
 
+	if (data->undetermined)
+	{
+		*s_tail = service = node_new (xstrdup ("undetermined"));
+		p_tail = &service->children;
+
+		size_t block = 8 * sizeof *data->undetermined;
+		for (size_t i = 0; i < 65536 / block; i++)
+			for (size_t k = 0; k < block; k++)
+			{
+				if (!(data->undetermined[i] & (1 << k)))
+					continue;
+
+				port = *p_tail = node_new (xstrdup_printf
+					("port %" PRIu16, (uint16_t) (i * block + k)));
+				p_tail = &port->next;
+			}
+	}
+
 	node_print_tree (root);
 	node_delete (root);
 	putchar ('\n');
@@ -1432,20 +1472,42 @@ target_dump_results (struct target *self)
 	struct app_context *ctx = self->ctx;
 	struct target_dump_data data;
 
+	// Equals { successfully connected } \ { any service detected }
+	static uint32_t undetermined[65536 / 32];
+	memset (undetermined, 0, sizeof undetermined);
+
 	size_t len = 0;
 	for (struct unit *iter = self->results; iter; iter = iter->next)
-		len++;
+	{
+		if (iter->success)
+			len++;
+		else
+			undetermined[iter->port / 32] |=   1 << (iter->port % 32);
+	}
 
 	struct unit *sorted[len];
 	data.results = sorted;
 	data.results_len = len;
 
 	for (struct unit *iter = self->results; iter; iter = iter->next)
-		sorted[--len] = iter;
+		if (iter->success)
+		{
+			sorted[--len] = iter;
+			undetermined[iter->port / 32] &= ~(1 << (iter->port % 32));
+		}
 
 	// Sort them by service name so that they can be grouped
 	qsort (sorted, N_ELEMENTS (sorted), sizeof *sorted, unit_cmp_by_order);
 
+	// Only set the field if there were any undetermined services at all
+	data.undetermined = NULL;
+	for (size_t i = 0; i < N_ELEMENTS (undetermined); i++)
+		if (undetermined[i])
+		{
+			data.undetermined = undetermined;
+			break;
+		}
+
 	if (ctx->json_results)
 		target_dump_json (self, &data);
 	target_dump_terminal (self, &data);
-- 
cgit v1.2.3-70-g09d2