1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012-2016 Pablo Neira Ayuso <pablo@netfilter.org>
6 #include <linux/init.h>
7 #include <linux/module.h>
8 #include <linux/skbuff.h>
9 #include <linux/netlink.h>
10 #include <linux/netfilter.h>
11 #include <linux/netfilter/nf_tables.h>
12 #include <net/netfilter/nf_tables_core.h>
14 #define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr))
16 void nft_objref_eval(const struct nft_expr
*expr
,
17 struct nft_regs
*regs
,
18 const struct nft_pktinfo
*pkt
)
20 struct nft_object
*obj
= nft_objref_priv(expr
);
22 obj
->ops
->eval(obj
, regs
, pkt
);
25 static int nft_objref_init(const struct nft_ctx
*ctx
,
26 const struct nft_expr
*expr
,
27 const struct nlattr
* const tb
[])
29 struct nft_object
*obj
= nft_objref_priv(expr
);
30 u8 genmask
= nft_genmask_next(ctx
->net
);
33 if (!tb
[NFTA_OBJREF_IMM_NAME
] ||
34 !tb
[NFTA_OBJREF_IMM_TYPE
])
37 objtype
= ntohl(nla_get_be32(tb
[NFTA_OBJREF_IMM_TYPE
]));
38 obj
= nft_obj_lookup(ctx
->net
, ctx
->table
,
39 tb
[NFTA_OBJREF_IMM_NAME
], objtype
,
44 if (!nft_use_inc(&obj
->use
))
47 nft_objref_priv(expr
) = obj
;
52 static int nft_objref_dump(struct sk_buff
*skb
,
53 const struct nft_expr
*expr
, bool reset
)
55 const struct nft_object
*obj
= nft_objref_priv(expr
);
57 if (nla_put_string(skb
, NFTA_OBJREF_IMM_NAME
, obj
->key
.name
) ||
58 nla_put_be32(skb
, NFTA_OBJREF_IMM_TYPE
,
59 htonl(obj
->ops
->type
->type
)))
68 static void nft_objref_deactivate(const struct nft_ctx
*ctx
,
69 const struct nft_expr
*expr
,
70 enum nft_trans_phase phase
)
72 struct nft_object
*obj
= nft_objref_priv(expr
);
74 if (phase
== NFT_TRANS_COMMIT
)
77 nft_use_dec(&obj
->use
);
80 static void nft_objref_activate(const struct nft_ctx
*ctx
,
81 const struct nft_expr
*expr
)
83 struct nft_object
*obj
= nft_objref_priv(expr
);
85 nft_use_inc_restore(&obj
->use
);
88 static const struct nft_expr_ops nft_objref_ops
= {
89 .type
= &nft_objref_type
,
90 .size
= NFT_EXPR_SIZE(sizeof(struct nft_object
*)),
91 .eval
= nft_objref_eval
,
92 .init
= nft_objref_init
,
93 .activate
= nft_objref_activate
,
94 .deactivate
= nft_objref_deactivate
,
95 .dump
= nft_objref_dump
,
96 .reduce
= NFT_REDUCE_READONLY
,
99 struct nft_objref_map
{
102 struct nft_set_binding binding
;
105 void nft_objref_map_eval(const struct nft_expr
*expr
,
106 struct nft_regs
*regs
,
107 const struct nft_pktinfo
*pkt
)
109 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
110 const struct nft_set
*set
= priv
->set
;
111 struct net
*net
= nft_net(pkt
);
112 const struct nft_set_ext
*ext
;
113 struct nft_object
*obj
;
116 found
= nft_set_do_lookup(net
, set
, ®s
->data
[priv
->sreg
], &ext
);
118 ext
= nft_set_catchall_lookup(net
, set
);
120 regs
->verdict
.code
= NFT_BREAK
;
124 obj
= *nft_set_ext_obj(ext
);
125 obj
->ops
->eval(obj
, regs
, pkt
);
128 static int nft_objref_map_init(const struct nft_ctx
*ctx
,
129 const struct nft_expr
*expr
,
130 const struct nlattr
* const tb
[])
132 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
133 u8 genmask
= nft_genmask_next(ctx
->net
);
137 set
= nft_set_lookup_global(ctx
->net
, ctx
->table
,
138 tb
[NFTA_OBJREF_SET_NAME
],
139 tb
[NFTA_OBJREF_SET_ID
], genmask
);
143 if (!(set
->flags
& NFT_SET_OBJECT
))
146 err
= nft_parse_register_load(ctx
, tb
[NFTA_OBJREF_SET_SREG
], &priv
->sreg
,
151 priv
->binding
.flags
= set
->flags
& NFT_SET_OBJECT
;
153 err
= nf_tables_bind_set(ctx
, set
, &priv
->binding
);
161 static int nft_objref_map_dump(struct sk_buff
*skb
,
162 const struct nft_expr
*expr
, bool reset
)
164 const struct nft_objref_map
*priv
= nft_expr_priv(expr
);
166 if (nft_dump_register(skb
, NFTA_OBJREF_SET_SREG
, priv
->sreg
) ||
167 nla_put_string(skb
, NFTA_OBJREF_SET_NAME
, priv
->set
->name
))
168 goto nla_put_failure
;
176 static void nft_objref_map_deactivate(const struct nft_ctx
*ctx
,
177 const struct nft_expr
*expr
,
178 enum nft_trans_phase phase
)
180 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
182 nf_tables_deactivate_set(ctx
, priv
->set
, &priv
->binding
, phase
);
185 static void nft_objref_map_activate(const struct nft_ctx
*ctx
,
186 const struct nft_expr
*expr
)
188 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
190 nf_tables_activate_set(ctx
, priv
->set
);
193 static void nft_objref_map_destroy(const struct nft_ctx
*ctx
,
194 const struct nft_expr
*expr
)
196 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
198 nf_tables_destroy_set(ctx
, priv
->set
);
201 static const struct nft_expr_ops nft_objref_map_ops
= {
202 .type
= &nft_objref_type
,
203 .size
= NFT_EXPR_SIZE(sizeof(struct nft_objref_map
)),
204 .eval
= nft_objref_map_eval
,
205 .init
= nft_objref_map_init
,
206 .activate
= nft_objref_map_activate
,
207 .deactivate
= nft_objref_map_deactivate
,
208 .destroy
= nft_objref_map_destroy
,
209 .dump
= nft_objref_map_dump
,
210 .reduce
= NFT_REDUCE_READONLY
,
213 static const struct nft_expr_ops
*
214 nft_objref_select_ops(const struct nft_ctx
*ctx
,
215 const struct nlattr
* const tb
[])
217 if (tb
[NFTA_OBJREF_SET_SREG
] &&
218 (tb
[NFTA_OBJREF_SET_NAME
] ||
219 tb
[NFTA_OBJREF_SET_ID
]))
220 return &nft_objref_map_ops
;
221 else if (tb
[NFTA_OBJREF_IMM_NAME
] &&
222 tb
[NFTA_OBJREF_IMM_TYPE
])
223 return &nft_objref_ops
;
225 return ERR_PTR(-EOPNOTSUPP
);
228 static const struct nla_policy nft_objref_policy
[NFTA_OBJREF_MAX
+ 1] = {
229 [NFTA_OBJREF_IMM_NAME
] = { .type
= NLA_STRING
,
230 .len
= NFT_OBJ_MAXNAMELEN
- 1 },
231 [NFTA_OBJREF_IMM_TYPE
] = { .type
= NLA_U32
},
232 [NFTA_OBJREF_SET_SREG
] = { .type
= NLA_U32
},
233 [NFTA_OBJREF_SET_NAME
] = { .type
= NLA_STRING
,
234 .len
= NFT_SET_MAXNAMELEN
- 1 },
235 [NFTA_OBJREF_SET_ID
] = { .type
= NLA_U32
},
238 struct nft_expr_type nft_objref_type __read_mostly
= {
240 .select_ops
= nft_objref_select_ops
,
241 .policy
= nft_objref_policy
,
242 .maxattr
= NFTA_OBJREF_MAX
,
243 .owner
= THIS_MODULE
,