2 * Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/list.h>
14 #include <linux/rbtree.h>
15 #include <linux/netlink.h>
16 #include <linux/netfilter.h>
17 #include <linux/netfilter/nf_tables.h>
18 #include <net/netfilter/nf_tables.h>
19 #include <net/netfilter/nf_tables_core.h>
23 enum nft_registers sreg
:8;
24 enum nft_registers dreg
:8;
26 struct nft_set_binding binding
;
29 static void nft_lookup_eval(const struct nft_expr
*expr
,
30 struct nft_regs
*regs
,
31 const struct nft_pktinfo
*pkt
)
33 const struct nft_lookup
*priv
= nft_expr_priv(expr
);
34 const struct nft_set
*set
= priv
->set
;
35 const struct nft_set_ext
*ext
;
38 found
= set
->ops
->lookup(pkt
->net
, set
, ®s
->data
[priv
->sreg
], &ext
) ^
42 regs
->verdict
.code
= NFT_BREAK
;
46 if (set
->flags
& NFT_SET_MAP
)
47 nft_data_copy(®s
->data
[priv
->dreg
],
48 nft_set_ext_data(ext
), set
->dlen
);
52 static const struct nla_policy nft_lookup_policy
[NFTA_LOOKUP_MAX
+ 1] = {
53 [NFTA_LOOKUP_SET
] = { .type
= NLA_STRING
},
54 [NFTA_LOOKUP_SET_ID
] = { .type
= NLA_U32
},
55 [NFTA_LOOKUP_SREG
] = { .type
= NLA_U32
},
56 [NFTA_LOOKUP_DREG
] = { .type
= NLA_U32
},
57 [NFTA_LOOKUP_FLAGS
] = { .type
= NLA_U32
},
60 static int nft_lookup_init(const struct nft_ctx
*ctx
,
61 const struct nft_expr
*expr
,
62 const struct nlattr
* const tb
[])
64 struct nft_lookup
*priv
= nft_expr_priv(expr
);
65 u8 genmask
= nft_genmask_next(ctx
->net
);
70 if (tb
[NFTA_LOOKUP_SET
] == NULL
||
71 tb
[NFTA_LOOKUP_SREG
] == NULL
)
74 set
= nf_tables_set_lookup(ctx
->table
, tb
[NFTA_LOOKUP_SET
], genmask
);
76 if (tb
[NFTA_LOOKUP_SET_ID
]) {
77 set
= nf_tables_set_lookup_byid(ctx
->net
,
78 tb
[NFTA_LOOKUP_SET_ID
],
85 if (set
->flags
& NFT_SET_EVAL
)
88 priv
->sreg
= nft_parse_register(tb
[NFTA_LOOKUP_SREG
]);
89 err
= nft_validate_register_load(priv
->sreg
, set
->klen
);
93 if (tb
[NFTA_LOOKUP_FLAGS
]) {
94 flags
= ntohl(nla_get_be32(tb
[NFTA_LOOKUP_FLAGS
]));
96 if (flags
& ~NFT_LOOKUP_F_INV
)
99 if (flags
& NFT_LOOKUP_F_INV
) {
100 if (set
->flags
& NFT_SET_MAP
)
106 if (tb
[NFTA_LOOKUP_DREG
] != NULL
) {
109 if (!(set
->flags
& NFT_SET_MAP
))
112 priv
->dreg
= nft_parse_register(tb
[NFTA_LOOKUP_DREG
]);
113 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
114 set
->dtype
, set
->dlen
);
117 } else if (set
->flags
& NFT_SET_MAP
)
120 priv
->binding
.flags
= set
->flags
& NFT_SET_MAP
;
122 err
= nf_tables_bind_set(ctx
, set
, &priv
->binding
);
130 static void nft_lookup_destroy(const struct nft_ctx
*ctx
,
131 const struct nft_expr
*expr
)
133 struct nft_lookup
*priv
= nft_expr_priv(expr
);
135 nf_tables_unbind_set(ctx
, priv
->set
, &priv
->binding
);
138 static int nft_lookup_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
140 const struct nft_lookup
*priv
= nft_expr_priv(expr
);
141 u32 flags
= priv
->invert
? NFT_LOOKUP_F_INV
: 0;
143 if (nla_put_string(skb
, NFTA_LOOKUP_SET
, priv
->set
->name
))
144 goto nla_put_failure
;
145 if (nft_dump_register(skb
, NFTA_LOOKUP_SREG
, priv
->sreg
))
146 goto nla_put_failure
;
147 if (priv
->set
->flags
& NFT_SET_MAP
)
148 if (nft_dump_register(skb
, NFTA_LOOKUP_DREG
, priv
->dreg
))
149 goto nla_put_failure
;
150 if (nla_put_be32(skb
, NFTA_LOOKUP_FLAGS
, htonl(flags
)))
151 goto nla_put_failure
;
158 static struct nft_expr_type nft_lookup_type
;
159 static const struct nft_expr_ops nft_lookup_ops
= {
160 .type
= &nft_lookup_type
,
161 .size
= NFT_EXPR_SIZE(sizeof(struct nft_lookup
)),
162 .eval
= nft_lookup_eval
,
163 .init
= nft_lookup_init
,
164 .destroy
= nft_lookup_destroy
,
165 .dump
= nft_lookup_dump
,
168 static struct nft_expr_type nft_lookup_type __read_mostly
= {
170 .ops
= &nft_lookup_ops
,
171 .policy
= nft_lookup_policy
,
172 .maxattr
= NFTA_LOOKUP_MAX
,
173 .owner
= THIS_MODULE
,
176 int __init
nft_lookup_module_init(void)
178 return nft_register_expr(&nft_lookup_type
);
181 void nft_lookup_module_exit(void)
183 nft_unregister_expr(&nft_lookup_type
);