2 * Copyright (c) 2012-2016 Pablo Neira Ayuso <pablo@netfilter.org>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
12 #include <linux/netlink.h>
13 #include <linux/netfilter.h>
14 #include <linux/netfilter/nf_tables.h>
15 #include <net/netfilter/nf_tables.h>
17 #define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr))
19 static void nft_objref_eval(const struct nft_expr
*expr
,
20 struct nft_regs
*regs
,
21 const struct nft_pktinfo
*pkt
)
23 struct nft_object
*obj
= nft_objref_priv(expr
);
25 obj
->ops
->eval(obj
, regs
, pkt
);
28 static int nft_objref_init(const struct nft_ctx
*ctx
,
29 const struct nft_expr
*expr
,
30 const struct nlattr
* const tb
[])
32 struct nft_object
*obj
= nft_objref_priv(expr
);
33 u8 genmask
= nft_genmask_next(ctx
->net
);
36 if (!tb
[NFTA_OBJREF_IMM_NAME
] ||
37 !tb
[NFTA_OBJREF_IMM_TYPE
])
40 objtype
= ntohl(nla_get_be32(tb
[NFTA_OBJREF_IMM_TYPE
]));
41 obj
= nf_tables_obj_lookup(ctx
->table
, tb
[NFTA_OBJREF_IMM_NAME
], objtype
,
46 nft_objref_priv(expr
) = obj
;
52 static int nft_objref_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
54 const struct nft_object
*obj
= nft_objref_priv(expr
);
56 if (nla_put_string(skb
, NFTA_OBJREF_IMM_NAME
, obj
->name
) ||
57 nla_put_be32(skb
, NFTA_OBJREF_IMM_TYPE
,
58 htonl(obj
->ops
->type
->type
)))
67 static void nft_objref_destroy(const struct nft_ctx
*ctx
,
68 const struct nft_expr
*expr
)
70 struct nft_object
*obj
= nft_objref_priv(expr
);
75 static struct nft_expr_type nft_objref_type
;
76 static const struct nft_expr_ops nft_objref_ops
= {
77 .type
= &nft_objref_type
,
78 .size
= NFT_EXPR_SIZE(sizeof(struct nft_object
*)),
79 .eval
= nft_objref_eval
,
80 .init
= nft_objref_init
,
81 .destroy
= nft_objref_destroy
,
82 .dump
= nft_objref_dump
,
85 struct nft_objref_map
{
87 enum nft_registers sreg
:8;
88 struct nft_set_binding binding
;
91 static void nft_objref_map_eval(const struct nft_expr
*expr
,
92 struct nft_regs
*regs
,
93 const struct nft_pktinfo
*pkt
)
95 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
96 const struct nft_set
*set
= priv
->set
;
97 const struct nft_set_ext
*ext
;
98 struct nft_object
*obj
;
101 found
= set
->ops
->lookup(nft_net(pkt
), set
, ®s
->data
[priv
->sreg
],
104 regs
->verdict
.code
= NFT_BREAK
;
107 obj
= *nft_set_ext_obj(ext
);
108 obj
->ops
->eval(obj
, regs
, pkt
);
111 static int nft_objref_map_init(const struct nft_ctx
*ctx
,
112 const struct nft_expr
*expr
,
113 const struct nlattr
* const tb
[])
115 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
116 u8 genmask
= nft_genmask_next(ctx
->net
);
120 set
= nft_set_lookup(ctx
->net
, ctx
->table
, tb
[NFTA_OBJREF_SET_NAME
],
121 tb
[NFTA_OBJREF_SET_ID
], genmask
);
125 if (!(set
->flags
& NFT_SET_OBJECT
))
128 priv
->sreg
= nft_parse_register(tb
[NFTA_OBJREF_SET_SREG
]);
129 err
= nft_validate_register_load(priv
->sreg
, set
->klen
);
133 priv
->binding
.flags
= set
->flags
& NFT_SET_OBJECT
;
135 err
= nf_tables_bind_set(ctx
, set
, &priv
->binding
);
143 static int nft_objref_map_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
145 const struct nft_objref_map
*priv
= nft_expr_priv(expr
);
147 if (nft_dump_register(skb
, NFTA_OBJREF_SET_SREG
, priv
->sreg
) ||
148 nla_put_string(skb
, NFTA_OBJREF_SET_NAME
, priv
->set
->name
))
149 goto nla_put_failure
;
157 static void nft_objref_map_destroy(const struct nft_ctx
*ctx
,
158 const struct nft_expr
*expr
)
160 struct nft_objref_map
*priv
= nft_expr_priv(expr
);
162 nf_tables_unbind_set(ctx
, priv
->set
, &priv
->binding
);
165 static struct nft_expr_type nft_objref_type
;
166 static const struct nft_expr_ops nft_objref_map_ops
= {
167 .type
= &nft_objref_type
,
168 .size
= NFT_EXPR_SIZE(sizeof(struct nft_objref_map
)),
169 .eval
= nft_objref_map_eval
,
170 .init
= nft_objref_map_init
,
171 .destroy
= nft_objref_map_destroy
,
172 .dump
= nft_objref_map_dump
,
175 static const struct nft_expr_ops
*
176 nft_objref_select_ops(const struct nft_ctx
*ctx
,
177 const struct nlattr
* const tb
[])
179 if (tb
[NFTA_OBJREF_SET_SREG
] &&
180 (tb
[NFTA_OBJREF_SET_NAME
] ||
181 tb
[NFTA_OBJREF_SET_ID
]))
182 return &nft_objref_map_ops
;
183 else if (tb
[NFTA_OBJREF_IMM_NAME
] &&
184 tb
[NFTA_OBJREF_IMM_TYPE
])
185 return &nft_objref_ops
;
187 return ERR_PTR(-EOPNOTSUPP
);
190 static const struct nla_policy nft_objref_policy
[NFTA_OBJREF_MAX
+ 1] = {
191 [NFTA_OBJREF_IMM_NAME
] = { .type
= NLA_STRING
,
192 .len
= NFT_OBJ_MAXNAMELEN
- 1 },
193 [NFTA_OBJREF_IMM_TYPE
] = { .type
= NLA_U32
},
194 [NFTA_OBJREF_SET_SREG
] = { .type
= NLA_U32
},
195 [NFTA_OBJREF_SET_NAME
] = { .type
= NLA_STRING
,
196 .len
= NFT_SET_MAXNAMELEN
- 1 },
197 [NFTA_OBJREF_SET_ID
] = { .type
= NLA_U32
},
200 static struct nft_expr_type nft_objref_type __read_mostly
= {
202 .select_ops
= nft_objref_select_ops
,
203 .policy
= nft_objref_policy
,
204 .maxattr
= NFTA_OBJREF_MAX
,
205 .owner
= THIS_MODULE
,
208 static int __init
nft_objref_module_init(void)
210 return nft_register_expr(&nft_objref_type
);
213 static void __exit
nft_objref_module_exit(void)
215 nft_unregister_expr(&nft_objref_type
);
218 module_init(nft_objref_module_init
);
219 module_exit(nft_objref_module_exit
);
221 MODULE_LICENSE("GPL");
222 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
223 MODULE_ALIAS_NFT_EXPR("objref");