[PATCH v2 1/3] conntrack: use libmnl for updating conntrack table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Use libmnl and libnetfilter_conntrack mnl helpers to update the conntrack
table entries.

Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@xxxxxxxxx>
---
 src/conntrack.c | 268 +++++++++++++++++++++++++++++-------------------
 1 file changed, 163 insertions(+), 105 deletions(-)

diff --git a/src/conntrack.c b/src/conntrack.c
index fe5574d..161e6a5 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -68,10 +68,13 @@
 #include <linux/netfilter/nf_conntrack_common.h>
 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
 
-static struct nfct_mnl_socket {
+struct nfct_mnl_socket {
 	struct mnl_socket	*mnl;
 	uint32_t		portid;
-} _sock;
+};
+
+static struct nfct_mnl_socket _sock;
+static struct nfct_mnl_socket _modifier_sock;
 
 struct u32_mask {
 	uint32_t value;
@@ -2073,33 +2076,6 @@ done:
 	return NFCT_CB_CONTINUE;
 }
 
-static int print_cb(enum nf_conntrack_msg_type type,
-		    struct nf_conntrack *ct,
-		    void *data)
-{
-	char buf[1024];
-	unsigned int op_type = NFCT_O_DEFAULT;
-	unsigned int op_flags = 0;
-
-	if (output_mask & _O_SAVE) {
-		ct_save_snprintf(buf, sizeof(buf), ct, labelmap, NFCT_T_NEW);
-		goto done;
-	}
-
-	if (output_mask & _O_XML)
-		op_type = NFCT_O_XML;
-	if (output_mask & _O_EXT)
-		op_flags = NFCT_OF_SHOW_LAYER3;
-	if (output_mask & _O_ID)
-		op_flags |= NFCT_OF_ID;
-
-	nfct_snprintf_labels(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, op_type, op_flags, labelmap);
-done:
-	printf("%s\n", buf);
-
-	return NFCT_CB_CONTINUE;
-}
-
 static void copy_mark(const struct ct_cmd *cmd, struct nf_conntrack *tmp,
 		      const struct nf_conntrack *ct,
 		      const struct u32_mask *m)
@@ -2190,73 +2166,6 @@ static void copy_label(const struct ct_cmd *cmd, struct nf_conntrack *tmp,
 	}
 }
 
-static int update_cb(enum nf_conntrack_msg_type type,
-		     struct nf_conntrack *ct,
-		     void *data)
-{
-	struct ct_cmd *cmd = data;
-	struct nf_conntrack *obj = cmd->tmpl.ct, *tmp;
-	int res;
-
-	if (filter_nat(cmd, ct) ||
-	    filter_label(ct, cur_tmpl) ||
-	    filter_network(cmd, ct))
-		return NFCT_CB_CONTINUE;
-
-	if (nfct_attr_is_set(obj, ATTR_ID) && nfct_attr_is_set(ct, ATTR_ID) &&
-	    nfct_get_attr_u32(obj, ATTR_ID) != nfct_get_attr_u32(ct, ATTR_ID))
-	    	return NFCT_CB_CONTINUE;
-
-	if (cmd->options & CT_OPT_TUPLE_ORIG &&
-	    !nfct_cmp(obj, ct, NFCT_CMP_ORIG))
-		return NFCT_CB_CONTINUE;
-	if (cmd->options & CT_OPT_TUPLE_REPL &&
-	    !nfct_cmp(obj, ct, NFCT_CMP_REPL))
-		return NFCT_CB_CONTINUE;
-
-	tmp = nfct_new();
-	if (tmp == NULL)
-		exit_error(OTHER_PROBLEM, "out of memory");
-
-	nfct_copy(tmp, ct, NFCT_CP_ORIG);
-	nfct_copy(tmp, obj, NFCT_CP_META);
-	copy_mark(cmd, tmp, ct, &cur_tmpl->mark);
-	copy_status(cmd, tmp, ct);
-	copy_label(cmd, tmp, ct, cur_tmpl);
-
-	/* do not send NFCT_Q_UPDATE if ct appears unchanged */
-	if (nfct_cmp(tmp, ct, NFCT_CMP_ALL | NFCT_CMP_MASK)) {
-		nfct_destroy(tmp);
-		return NFCT_CB_CONTINUE;
-	}
-
-	res = nfct_query(ith, NFCT_Q_UPDATE, tmp);
-	if (res < 0)
-		fprintf(stderr,
-			   "Operation failed: %s\n",
-			   err2str(errno, CT_UPDATE));
-	nfct_callback_register(ith, NFCT_T_ALL, print_cb, NULL);
-
-	res = nfct_query(ith, NFCT_Q_GET, tmp);
-	if (res < 0) {
-		nfct_destroy(tmp);
-		/* the entry has vanish in middle of the update */
-		if (errno == ENOENT) {
-			nfct_callback_unregister(ith);
-			return NFCT_CB_CONTINUE;
-		}
-		exit_error(OTHER_PROBLEM,
-			   "Operation failed: %s",
-			   err2str(errno, CT_UPDATE));
-	}
-	nfct_destroy(tmp);
-	nfct_callback_unregister(ith);
-
-	counter++;
-
-	return NFCT_CB_CONTINUE;
-}
-
 static int dump_exp_cb(enum nf_conntrack_msg_type type,
 		      struct nf_expect *exp,
 		      void *data)
@@ -2529,6 +2438,45 @@ nfct_mnl_create(struct nfct_mnl_socket *sock, uint16_t subsys, uint16_t type,
 	return nfct_mnl_talk(sock, nlh, NULL);
 }
 
+static int
+nfct_mnl_set_ct(struct nfct_mnl_socket *sock,
+		uint16_t subsys, uint16_t type, const struct nf_conntrack *ct)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	int res;
+
+	nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type,
+				    NLM_F_ACK,
+				    nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO));
+
+	res = nfct_nlmsg_build(nlh, ct);
+	if (res < 0)
+		return res;
+
+	return nfct_mnl_talk(sock, nlh, NULL);
+}
+
+static int
+nfct_mnl_request(struct nfct_mnl_socket *sock,
+		uint16_t subsys, uint16_t type, const struct nf_conntrack *ct,
+		mnl_cb_t cb)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct nlmsghdr *nlh;
+	int res;
+
+	nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type,
+				    NLM_F_ACK,
+				    nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO));
+
+	res = nfct_nlmsg_build(nlh, ct);
+	if (res < 0)
+		return res;
+
+	return nfct_mnl_recv(sock, nlh, cb, NULL);
+}
+
 #define UNKNOWN_STATS_NUM 4
 
 static int nfct_stats_attr_cb(const struct nlattr *attr, void *data)
@@ -2717,6 +2665,116 @@ done:
 	return MNL_CB_OK;
 }
 
+static int mnl_nfct_print_cb(const struct nlmsghdr *nlh, void *data)
+{
+	char buf[1024];
+	unsigned int op_type = NFCT_O_DEFAULT;
+	unsigned int op_flags = 0;
+	struct nf_conntrack *ct;
+
+	ct = nfct_new();
+	if (ct == NULL)
+		return MNL_CB_OK;
+
+	nfct_nlmsg_parse(nlh, ct);
+
+	if (output_mask & _O_SAVE) {
+		ct_save_snprintf(buf, sizeof(buf), ct, labelmap, NFCT_T_NEW);
+		goto done;
+	}
+
+	if (output_mask & _O_XML)
+		op_type = NFCT_O_XML;
+	if (output_mask & _O_EXT)
+		op_flags = NFCT_OF_SHOW_LAYER3;
+	if (output_mask & _O_ID)
+		op_flags |= NFCT_OF_ID;
+
+	nfct_snprintf_labels(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, op_type, op_flags, labelmap);
+done:
+	printf("%s\n", buf);
+
+	nfct_destroy(ct);
+
+	return MNL_CB_OK;
+}
+
+static int mnl_nfct_update_cb(const struct nlmsghdr *nlh, void *data)
+{
+	struct ct_cmd *cmd = data;
+	struct nfct_mnl_socket *modifier_sock = &_modifier_sock;
+	struct nf_conntrack *ct, *obj = cmd->tmpl.ct, *tmp = NULL;
+	int res;
+
+	ct = nfct_new();
+	if (ct == NULL)
+		return MNL_CB_OK;
+
+	nfct_nlmsg_parse(nlh, ct);
+
+	if (filter_nat(cmd, ct) ||
+	    filter_label(ct, cur_tmpl) ||
+	    filter_network(cmd, ct))
+		goto destroy_ok;
+
+	if (nfct_attr_is_set(obj, ATTR_ID) && nfct_attr_is_set(ct, ATTR_ID) &&
+	    nfct_get_attr_u32(obj, ATTR_ID) != nfct_get_attr_u32(ct, ATTR_ID))
+		goto destroy_ok;
+
+	if (cmd->options & CT_OPT_TUPLE_ORIG &&
+	    !nfct_cmp(obj, ct, NFCT_CMP_ORIG))
+		goto destroy_ok;
+	if (cmd->options & CT_OPT_TUPLE_REPL &&
+	    !nfct_cmp(obj, ct, NFCT_CMP_REPL))
+		goto destroy_ok;
+
+	tmp = nfct_new();
+	if (tmp == NULL)
+		exit_error(OTHER_PROBLEM, "out of memory");
+
+	nfct_copy(tmp, ct, NFCT_CP_ORIG);
+	nfct_copy(tmp, obj, NFCT_CP_META);
+	copy_mark(cmd, tmp, ct, &cur_tmpl->mark);
+	copy_status(cmd, tmp, ct);
+	copy_label(cmd, tmp, ct, cur_tmpl);
+
+	/* do not send NFCT_Q_UPDATE if ct appears unchanged */
+	if (nfct_cmp(tmp, ct, NFCT_CMP_ALL | NFCT_CMP_MASK))
+		goto destroy_ok;
+
+	res = nfct_mnl_set_ct(modifier_sock,
+			      NFNL_SUBSYS_CTNETLINK,
+			      IPCTNL_MSG_CT_NEW,
+			      tmp);
+	if (res < 0)
+		fprintf(stderr,
+			"Operation failed: %s\n",
+			err2str(errno, CT_UPDATE));
+
+	res = nfct_mnl_request(modifier_sock,
+			     NFNL_SUBSYS_CTNETLINK,
+			     IPCTNL_MSG_CT_GET,
+			     tmp,
+			     mnl_nfct_print_cb);
+	if (res < 0) {
+		/* the entry has vanish in middle of the update */
+		if (errno == ENOENT)
+			goto destroy_ok;
+		exit_error(OTHER_PROBLEM,
+			   "Operation failed: %s",
+			   err2str(errno, CT_UPDATE));
+	}
+
+	counter++;
+
+destroy_ok:
+	if (tmp)
+		nfct_destroy(tmp);
+	nfct_destroy(ct);
+
+	return MNL_CB_OK;
+}
+
 static struct ctproto_handler *h;
 
 static void labelmap_init(void)
@@ -3253,6 +3311,7 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[])
 static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 {
 	struct nfct_mnl_socket *sock = &_sock;
+	struct nfct_mnl_socket *modifier_sock = &_modifier_sock;
 	struct nfct_filter_dump *filter_dump;
 	int res = 0;
 
@@ -3373,19 +3432,18 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
 		break;
 
 	case CT_UPDATE:
-		cth = nfct_open(CONNTRACK, 0);
-		/* internal handler for delete_cb, otherwise we hit EILSEQ */
-		ith = nfct_open(CONNTRACK, 0);
-		if (!cth || !ith)
+		if (nfct_mnl_socket_open(sock, 0) < 0
+		    || nfct_mnl_socket_open(modifier_sock, 0) < 0)
 			exit_error(OTHER_PROBLEM, "Can't open handler");
 
 		nfct_filter_init(cmd);
 
-		nfct_callback_register(cth, NFCT_T_ALL, update_cb, cmd);
-
-		res = nfct_query(cth, NFCT_Q_DUMP, &cmd->family);
-		nfct_close(ith);
-		nfct_close(cth);
+		res = nfct_mnl_dump(sock,
+				    NFNL_SUBSYS_CTNETLINK,
+				    IPCTNL_MSG_CT_GET,
+				    mnl_nfct_update_cb, cmd, NULL);
+		nfct_mnl_socket_close(modifier_sock);
+		nfct_mnl_socket_close(sock);
 		break;
 
 	case CT_DELETE:
-- 
2.25.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux