[PATCH 2/4] libnftnl: set: Add new attribute into 'set' to store an arbitrary length user data.

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

 



The new structure 'user' holds a pointer to user data and its length. The
kernel must have the flag NFTA_SET_USERDATA to support this feature.

Signed-off-by: Carlos Falgueras García <carlosfg@xxxxxxxxxx>
---
 include/libnftnl/set.h              |  2 ++
 include/linux/netfilter/nf_tables.h |  2 ++
 include/set.h                       |  4 +++
 src/set.c                           | 50 +++++++++++++++++++++++++++++++++++++
 4 files changed, 58 insertions(+)

diff --git a/include/libnftnl/set.h b/include/libnftnl/set.h
index 11243f5..7a5a512 100644
--- a/include/libnftnl/set.h
+++ b/include/libnftnl/set.h
@@ -22,6 +22,7 @@ enum nftnl_set_attr {
 	NFTNL_SET_DESC_SIZE,
 	NFTNL_SET_TIMEOUT,
 	NFTNL_SET_GC_INTERVAL,
+	NFTNL_SET_USERDATA,
 	__NFTNL_SET_MAX
 };
 #define NFTNL_SET_MAX (__NFTNL_SET_MAX - 1)
@@ -158,6 +159,7 @@ enum {
 	NFT_SET_ATTR_DESC_SIZE,
 	NFT_SET_ATTR_TIMEOUT,
 	NFT_SET_ATTR_GC_INTERVAL,
+	NFT_SET_ATTR_USERDATA,
 	__NFT_SET_ATTR_MAX
 };
 #define NFT_SET_ATTR_MAX (__NFT_SET_ATTR_MAX - 1)
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index f77693b..9beddc5 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -291,6 +291,7 @@ enum nft_set_desc_attributes {
  * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
  * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
  * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
+ * @NFTA_SET_USERDATA: user data (NLA_BINARY)
  */
 enum nft_set_attributes {
 	NFTA_SET_UNSPEC,
@@ -306,6 +307,7 @@ enum nft_set_attributes {
 	NFTA_SET_ID,
 	NFTA_SET_TIMEOUT,
 	NFTA_SET_GC_INTERVAL,
+	NFTA_SET_USERDATA,
 	__NFTA_SET_MAX
 };
 #define NFTA_SET_MAX		(__NFTA_SET_MAX - 1)
diff --git a/include/set.h b/include/set.h
index c3b96f2..85bd389 100644
--- a/include/set.h
+++ b/include/set.h
@@ -14,6 +14,10 @@ struct nftnl_set {
 	uint32_t		key_len;
 	uint32_t		data_type;
 	uint32_t		data_len;
+	struct {
+		void		*data;
+		uint32_t	len;
+	} user;
 	uint32_t		id;
 	enum nft_set_policies	policy;
 	struct {
diff --git a/src/set.c b/src/set.c
index 8369f7f..315bced 100644
--- a/src/set.c
+++ b/src/set.c
@@ -19,6 +19,7 @@
 #include <netinet/in.h>
 #include <limits.h>
 #include <errno.h>
+#include <ctype.h>
 
 #include <libmnl/libmnl.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -91,6 +92,7 @@ void nftnl_set_unset(struct nftnl_set *s, uint16_t attr)
 	case NFTNL_SET_DESC_SIZE:
 	case NFTNL_SET_TIMEOUT:
 	case NFTNL_SET_GC_INTERVAL:
+	case NFTNL_SET_USERDATA:
 		break;
 	default:
 		return;
@@ -167,6 +169,10 @@ void nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data,
 	case NFTNL_SET_GC_INTERVAL:
 		s->gc_interval = *((uint32_t *)data);
 		break;
+	case NFTNL_SET_USERDATA:
+		s->user.data = (void *)data;
+		s->user.len  = data_len;
+		break;
 	}
 	s->flags |= (1 << attr);
 }
@@ -240,6 +246,9 @@ const void *nftnl_set_get_data(struct nftnl_set *s, uint16_t attr,
 	case NFTNL_SET_GC_INTERVAL:
 		*data_len = sizeof(uint32_t);
 		return &s->gc_interval;
+	case NFTNL_SET_USERDATA:
+		*data_len = s->user.len;
+		return s->user.data;
 	}
 	return NULL;
 }
@@ -348,6 +357,8 @@ void nftnl_set_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
 		mnl_attr_put_u64(nlh, NFTA_SET_TIMEOUT, htobe64(s->timeout));
 	if (s->flags & (1 << NFTNL_SET_GC_INTERVAL))
 		mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
+	if (s->flags & (1 << NFTNL_SET_USERDATA))
+		mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
 }
 EXPORT_SYMBOL_ALIAS(nftnl_set_nlmsg_build_payload, nft_set_nlmsg_build_payload);
 
@@ -376,6 +387,10 @@ static int nftnl_set_parse_attr_cb(const struct nlattr *attr, void *data)
 		if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
 			abi_breakage();
 		break;
+	case NFTA_SET_USERDATA:
+		if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
+			abi_breakage();
+		break;
 	case NFTA_SET_TIMEOUT:
 		if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
 			abi_breakage();
@@ -480,6 +495,20 @@ int nftnl_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s)
 		s->gc_interval = ntohl(mnl_attr_get_u32(tb[NFTA_SET_GC_INTERVAL]));
 		s->flags |= (1 << NFTNL_SET_GC_INTERVAL);
 	}
+	if (tb[NFTA_SET_USERDATA]) {
+		const void *udata =
+			mnl_attr_get_payload(tb[NFTA_SET_USERDATA]);
+
+		if (s->user.data)
+			xfree(s->user.data);
+
+		s->user.len  = mnl_attr_get_payload_len(tb[NFTA_SET_USERDATA]);
+		s->user.data = malloc(s->user.len);
+		if (s->user.data == NULL)
+			return -1;
+		memcpy(s->user.data, udata, s->user.len);
+		s->flags |= (1 << NFTNL_SET_USERDATA);
+	}
 	if (tb[NFTA_SET_DESC])
 		ret = nftnl_set_desc_parse(s, tb[NFTA_SET_DESC]);
 
@@ -775,6 +804,7 @@ static int nftnl_set_snprintf_json(char *buf, size_t size, struct nftnl_set *s,
 				  uint32_t type, uint32_t flags)
 {
 	int len = size, offset = 0, ret;
+	int i;
 	struct nftnl_set_elem *elem;
 
 	ret = snprintf(buf, len, "{\"set\":{");
@@ -826,6 +856,26 @@ static int nftnl_set_snprintf_json(char *buf, size_t size, struct nftnl_set *s,
 		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
 	}
 
+	if (s->flags & (1 << NFTNL_SET_USERDATA)) {
+		ret = snprintf(buf + offset, len, ",\"userdata_len\":%u",
+			       s->user.len);
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+		ret = snprintf(buf + offset, len, ",\"userdata\":\"");
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
+		char *c = s->user.data;
+
+		for (i = 0; i < s->user.len; i++) {
+			ret = snprintf(buf + offset, len, "%c",
+				       isprint(c[i]) ? c[i] : ' ');
+			SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+		}
+
+		ret = snprintf(buf + offset, len, "\"");
+		SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+	}
+
 	if (s->flags & (1 << NFTNL_SET_DESC_SIZE)) {
 		ret = snprintf(buf + offset, len, ",\"desc_size\":%u",
 			       s->desc.size);
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux