[PATCH nf-next 5/7] netfilter: nft_objref: add support for operation on objects

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

 



This patch allows you to specify what kind of operation you want to
perform on an object. Operations are object type specific. All objects
are assumed to have defined at least one operation (type 0).

Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
---
 include/net/netfilter/nf_tables.h        |  4 ++++
 include/uapi/linux/netfilter/nf_tables.h |  1 +
 net/netfilter/nf_tables_api.c            |  3 ++-
 net/netfilter/nft_objref.c               | 27 ++++++++++++++++++++++++---
 4 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 413eb650bafd..7a3f408d4328 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1100,6 +1100,8 @@ void nft_obj_notify(struct net *net, const struct nft_table *table,
 		    struct nft_object *obj, u32 portid, u32 seq,
 		    int event, int family, int report, gfp_t gfp);
 
+const struct nft_object_type *__nft_obj_type_get(u32 objtype);
+
 /**
  *	struct nft_object_type - stateful object type
  *
@@ -1118,12 +1120,14 @@ struct nft_object_type {
 	struct list_head		list;
 	u32				type;
 	unsigned int                    maxattr;
+	u32				maxops;
 	struct module			*owner;
 	const struct nla_policy		*policy;
 };
 
 struct nft_object_ref {
 	struct nft_object		*obj;
+	u8				op;
 };
 
 /**
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 100261902b1b..93326a544184 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1390,6 +1390,7 @@ enum nft_objref_attributes {
 	NFTA_OBJREF_SET_SREG,
 	NFTA_OBJREF_SET_NAME,
 	NFTA_OBJREF_SET_ID,
+	NFTA_OBJREF_OP,
 	__NFTA_OBJREF_MAX
 };
 #define NFTA_OBJREF_MAX	(__NFTA_OBJREF_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index ff04cdc87f76..b5051f4dbb26 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -5370,7 +5370,7 @@ static int nft_object_dump(struct sk_buff *skb, unsigned int attr,
 	return -1;
 }
 
-static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
+const struct nft_object_type *__nft_obj_type_get(u32 objtype)
 {
 	const struct nft_object_type *type;
 
@@ -5380,6 +5380,7 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(__nft_obj_type_get);
 
 static const struct nft_object_type *
 nft_obj_type_get(struct net *net, u32 objtype)
diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c
index 21ef987d5ac4..f3b99af031e2 100644
--- a/net/netfilter/nft_objref.c
+++ b/net/netfilter/nft_objref.c
@@ -40,6 +40,12 @@ static int nft_objref_init(const struct nft_ctx *ctx,
 	if (IS_ERR(obj))
 		return -ENOENT;
 
+	if (tb[NFTA_OBJREF_OP]) {
+		priv->op = ntohl(nla_get_be32(tb[NFTA_OBJREF_OP]));
+		if (priv->op > obj->ops->type->maxops)
+			return -EOPNOTSUPP;
+	}
+
 	obj->use++;
 	priv->obj = obj;
 
@@ -52,8 +58,8 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr)
 	const struct nft_object *obj = priv->obj;
 
 	if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->key.name) ||
-	    nla_put_be32(skb, NFTA_OBJREF_TYPE,
-			 htonl(obj->ops->type->type)))
+	    nla_put_be32(skb, NFTA_OBJREF_TYPE, htonl(obj->ops->type->type)) ||
+	    nla_put_be32(skb, NFTA_OBJREF_OP, htonl(priv->op)))
 		goto nla_put_failure;
 
 	return 0;
@@ -98,6 +104,7 @@ static const struct nft_expr_ops nft_objref_ops = {
 struct nft_objref_map {
 	struct nft_set		*set;
 	enum nft_registers	sreg:8;
+	u8			op;
 	struct nft_set_binding	binding;
 };
 
@@ -120,6 +127,7 @@ static void nft_objref_map_eval(const struct nft_expr *expr,
 	}
 	obj = *nft_set_ext_obj(ext);
 	ref.obj = obj;
+	ref.op 	= priv->op;
 	obj->ops->eval(&ref, regs, pkt);
 }
 
@@ -160,6 +168,18 @@ static int nft_objref_map_init(const struct nft_ctx *ctx,
 	    set->objtype != objtype)
 		return -EOPNOTSUPP;
 
+	if (tb[NFTA_OBJREF_OP]) {
+		const struct nft_object_type *type;
+
+		if (objtype == NFT_OBJECT_UNSPEC)
+			return -EOPNOTSUPP;
+
+		priv->op = ntohl(nla_get_be32(tb[NFTA_OBJREF_OP]));
+		type = __nft_obj_type_get(objtype);
+		if (!type || priv->op > type->maxops)
+			return -EOPNOTSUPP;
+	}
+
 	priv->set = set;
 	return 0;
 }
@@ -169,7 +189,8 @@ static int nft_objref_map_dump(struct sk_buff *skb, const struct nft_expr *expr)
 	const struct nft_objref_map *priv = nft_expr_priv(expr);
 
 	if (nft_dump_register(skb, NFTA_OBJREF_SET_SREG, priv->sreg) ||
-	    nla_put_string(skb, NFTA_OBJREF_SET_NAME, priv->set->name))
+	    nla_put_string(skb, NFTA_OBJREF_SET_NAME, priv->set->name) ||
+	    nla_put_be32(skb, NFTA_OBJREF_OP, htonl(priv->op)))
 		goto nla_put_failure;
 
 	return 0;
-- 
2.11.0




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

  Powered by Linux