[][MAC80211][hnat][Move Netfilter Netlink Ftnl package to feed]

[Description]
Refactor Netfilter Netlink Ftnl patch.

If without this patch, this package might not be applied on the RDKB.

[Release-log]
N/A


Change-Id: Iefdfdea1e4480ac5fe9195b0f8b1b52706b76b05
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7217027
diff --git a/feed/flowtable/src/api.c b/feed/flowtable/src/api.c
new file mode 100644
index 0000000..64bbbfe
--- /dev/null
+++ b/feed/flowtable/src/api.c
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netfilter_flowtable.h"
+
+static void attr_dump(struct nfattr *attr)
+{
+	char *data = nla_data(attr);
+	int i = 0;
+
+	while (i < nal_len(attr)) {
+		printf("%x ", *(data + i));
+		i++;
+		if (i % 16 == 0)
+			printf("\n");
+	}
+	printf("\n");
+}
+
+struct ftnl_handle *ftnl_open(void)
+{
+	struct ftnl_handle *h = NULL;
+
+	h = malloc(sizeof(struct ftnl_handle));
+	if (!h)
+		return NULL;
+
+	h->nfnlh = nfnl_open();
+	if (!h->nfnlh) {
+		printf("nfnl open fail\n");
+		free(h);
+		return NULL;
+	}
+
+	h->ftnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_FLOWTABLE, 1, 0);
+	if (!h->ftnlssh) {
+		nfnl_close(h->nfnlh);
+		printf("subsys open fail\n");
+		free(h);
+		return NULL;
+	}
+
+	return h;
+}
+
+void ftnl_close(struct ftnl_handle *h)
+{
+	nfnl_subsys_close(h->ftnlssh);
+	nfnl_close(h->nfnlh);
+	free(h);
+}
+
+static void build_tuple(struct nlmsghdr *nlh, size_t size,
+			struct flow_tuple *tuple)
+{
+	struct nfattr *nest_tuple, *nest_ip, *nest_proto;
+
+	nest_tuple = nfnl_nest(nlh, size, FTA_TUPLE);
+
+	nest_ip = nfnl_nest(nlh, size, FTA_TUPLE_IP);
+	nfnl_addattr_l(nlh, size, FTA_IP_V4_SRC,
+		       &tuple->sip4, sizeof(uint32_t));
+	nfnl_addattr_l(nlh, size, FTA_IP_V4_DST,
+		       &tuple->dip4, sizeof(uint32_t));
+	nfnl_nest_end(nlh, nest_ip);
+
+	nest_proto = nfnl_nest(nlh, size, FTA_TUPLE_PROTO);
+	nfnl_addattr_l(nlh, size, FTA_PROTO_NUM,
+		       &tuple->proto, sizeof(uint8_t));
+	nfnl_addattr_l(nlh, size, FTA_PROTO_SPORT,
+		       &tuple->sport, sizeof(uint16_t));
+	nfnl_addattr_l(nlh, size, FTA_PROTO_DPORT,
+		       &tuple->dport, sizeof(uint16_t));
+	nfnl_nest_end(nlh, nest_proto);
+
+	nfnl_nest_end(nlh, nest_tuple);
+//	attr_dump(nest_tuple);
+}
+
+int ftnl_flush_table(struct ftnl_handle *h)
+{
+	struct nlmsghdr nlh;
+	int ret;
+
+	/* construct msg */
+	nfnl_fill_hdr(h->ftnlssh, &nlh, 0, AF_INET, 0,
+		      FT_MSG_FLUSH, NLM_F_REQUEST | NLM_F_ACK);
+
+	/* send msg */
+	ret = nfnl_send(h->nfnlh, &nlh);
+	return ret;
+}
+
+int ftnl_del_flow(struct ftnl_handle *h, struct flow_tuple *tuple)
+{
+	const int size = 256;
+	union {
+		char buffer[size];
+		struct nlmsghdr nlh;
+	} u;
+	int ret;
+
+	/* construct msg */
+	nfnl_fill_hdr(h->ftnlssh, &u.nlh, 0, AF_INET, 0,
+		      FT_MSG_DEL, NLM_F_REQUEST|NLM_F_ACK);
+	build_tuple(&u.nlh, size, tuple);
+
+	/* send msg */
+	ret = nfnl_send(h->nfnlh, &u.nlh);
+
+	return ret;
+}