From c8928b4364eab3762ae94ecbd471a98f20c47462 Mon Sep 17 00:00:00 2001
From: Amit Kumar <amit.kumar@iopsys.eu>
Date: Tue, 9 May 2023 13:44:07 +0530
Subject: [PATCH] map-topology: conntrack to get active connections

handling done to fetch active conntrack connections for host.
used libconntracl netlink to fetch connections.
---
 src/host.c       | 27 +--------------
 src/host.h       |  1 +
 src/host_nodes.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 26 deletions(-)

diff --git a/src/host.c b/src/host.c
index e82d4e7..ceccced 100644
--- a/src/host.c
+++ b/src/host.c
@@ -655,31 +655,6 @@ void host_get_network_dump(struct topologyd_private *priv)
 	blob_buf_free(&bb);
 }
 
-/* TODO: taken from questd */
-static int active_connections(char *ipaddr)
-{
-	FILE *f;
-	int i;
-	char *p, line[512];
-	char *saveptr;
-	int connum = 0;
-
-	f = fopen("/proc/net/nf_conntrack", "r");
-
-	if (f != NULL) {
-		while (fgets(line, sizeof(line) - 1, f)) {
-			for (i = 0, p = strtok_r(line, " ", &saveptr); p; i++, p = strtok_r(NULL, " ", &saveptr)) {
-				if (i == 6 && strcmp(p+4, ipaddr) == 0)
-					connum++;
-			}
-		}
-
-		fclose(f);
-	}
-
-	return connum;
-}
-
 void get_bridge_info(struct host_node *host, char *device)
 {
 	char brinfo[16];
@@ -890,7 +865,7 @@ int host_get_ipaddr_hostname(struct topologyd_private *priv,
 
 	host_get_parent_iface(priv, p);
 
-	p->active_connections = active_connections(p->ipv4addr);
+	p->active_connections = active_connections(priv, p->ipv4addr);
 
 	ret = strncmp(p->ipv4addr, "", 24);
 	if (ret == 0)
diff --git a/src/host.h b/src/host.h
index 88e21e0..ccbcc5b 100644
--- a/src/host.h
+++ b/src/host.h
@@ -156,5 +156,6 @@ int host_node_get_statistics(struct topologyd_private *priv);
 int host_is_device_address(struct topologyd_private *priv, char *address, int family);
 int host_get_interface_type(struct topologyd_private *priv);
 int host_send_arp_req(char *ipaddr_str, char *ifname);
+int active_connections(struct topologyd_private *priv, char *ipaddr);
 
 #endif /* HOSTD_H */
diff --git a/src/host_nodes.c b/src/host_nodes.c
index 05274f7..a6cccc1 100644
--- a/src/host_nodes.c
+++ b/src/host_nodes.c
@@ -37,6 +37,12 @@ struct host_nf_tc {
 	struct host_node *host;
 };
 
+struct host_connection {
+	struct topologyd_private *priv;
+	unsigned int ipv4_addr;
+	unsigned int active_connections;
+};
+
 void host_node_destroy(struct host_node *n)
 {
 	free(n);
@@ -468,3 +474,82 @@ int host_node_get_statistics(struct topologyd_private *priv)
 	host_node_clean_nf_tc(priv);
 	return 0;
 }
+
+
+int host_active_connection (enum nf_conntrack_msg_type type,
+                            struct nf_conntrack *ct,
+                            void *data)
+{
+        int ret_val = 0;
+	struct nfct_attr_grp_ipv4 grp_ipv4;
+	struct in_addr addr;
+	struct host_connection *host_conn = (struct host_connection *) data;
+
+
+	ret_val=nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV4, &grp_ipv4);
+	if (ret_val)
+		return NFCT_CB_CONTINUE;
+
+	memcpy(&addr, &grp_ipv4.dst, sizeof(grp_ipv4.dst));
+	if (host_is_device_address(host_conn->priv, inet_ntoa(addr), AF_INET))
+		return NFCT_CB_CONTINUE;
+
+	if (grp_ipv4.src == host_conn->ipv4_addr) {
+		host_conn->active_connections++;
+	}
+	return NFCT_CB_CONTINUE;
+
+}
+
+int active_connections(struct topologyd_private *priv, char *ipaddr)
+{
+#ifdef ACTIVE_CONN_LIBCONNTRACK
+        struct nfct_handle *cth = NULL;
+        struct nfct_filter_dump *filter_dump = NULL;
+        struct nf_conntrack *ct = NULL;
+	struct sockaddr_in sa;
+	struct host_connection host_conn;
+
+	if (inet_pton(AF_INET, ipaddr, &(sa.sin_addr)) < 0)
+		return 0;
+	host_conn.ipv4_addr = sa.sin_addr.s_addr;
+	host_conn.priv = priv;
+	host_conn.active_connections = 0;
+
+	cth = nfct_open(CONNTRACK, 0);
+        if (!cth) {
+                err("Can't open handler\n");
+		return 0;
+	}
+        ct = nfct_new();
+	if (ct == NULL) {
+		err("%s Failed to create nfct instance\n", __FUNCTION__);
+		nfct_close(cth);
+		return 0;
+	}
+
+	nfct_set_attr_u8(ct, ATTR_ORIG_L3PROTO, AF_INET);
+	nfct_callback_register(cth, NFCT_T_NEW | NFCT_T_UPDATE, host_active_connection, &host_conn);
+
+        filter_dump = nfct_filter_dump_create();
+        if (filter_dump == NULL) {
+		nfct_destroy(ct);
+		nfct_close(cth);
+		err("%s Failed to allocate filter_dump", __FUNCTION__);
+		return 0;
+	}
+
+        nfct_filter_dump_set_attr_u8(filter_dump,
+                                     NFCT_FILTER_DUMP_L3NUM,
+                                     AF_INET);
+
+        nfct_query(cth, NFCT_Q_DUMP_FILTER, filter_dump);
+
+        nfct_filter_dump_destroy(filter_dump);
+	nfct_destroy(ct);
+	nfct_close(cth);
+	return host_conn.active_connections;
+#else
+	return 0;
+#endif
+}
-- 
GitLab