2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
6 * Generic part shared by ipv4 and ipv6 backends.
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/netlink.h>
13 #include <linux/netfilter.h>
14 #include <linux/netfilter/nf_tables.h>
15 #include <net/netfilter/nf_tables_core.h>
16 #include <net/netfilter/nf_tables.h>
17 #include <net/netfilter/nft_fib.h>
19 const struct nla_policy nft_fib_policy
[NFTA_FIB_MAX
+ 1] = {
20 [NFTA_FIB_DREG
] = { .type
= NLA_U32
},
21 [NFTA_FIB_RESULT
] = { .type
= NLA_U32
},
22 [NFTA_FIB_FLAGS
] = { .type
= NLA_U32
},
24 EXPORT_SYMBOL(nft_fib_policy
);
26 #define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
27 NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)
29 int nft_fib_validate(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
30 const struct nft_data
**data
)
32 const struct nft_fib
*priv
= nft_expr_priv(expr
);
35 switch (priv
->result
) {
36 case NFT_FIB_RESULT_OIF
: /* fallthrough */
37 case NFT_FIB_RESULT_OIFNAME
:
38 hooks
= (1 << NF_INET_PRE_ROUTING
);
40 case NFT_FIB_RESULT_ADDRTYPE
:
41 if (priv
->flags
& NFTA_FIB_F_IIF
)
42 hooks
= (1 << NF_INET_PRE_ROUTING
) |
43 (1 << NF_INET_LOCAL_IN
) |
44 (1 << NF_INET_FORWARD
);
45 else if (priv
->flags
& NFTA_FIB_F_OIF
)
46 hooks
= (1 << NF_INET_LOCAL_OUT
) |
47 (1 << NF_INET_POST_ROUTING
) |
48 (1 << NF_INET_FORWARD
);
50 hooks
= (1 << NF_INET_LOCAL_IN
) |
51 (1 << NF_INET_LOCAL_OUT
) |
52 (1 << NF_INET_FORWARD
) |
53 (1 << NF_INET_PRE_ROUTING
) |
54 (1 << NF_INET_POST_ROUTING
);
61 return nft_chain_validate_hooks(ctx
->chain
, hooks
);
63 EXPORT_SYMBOL_GPL(nft_fib_validate
);
65 int nft_fib_init(const struct nft_ctx
*ctx
, const struct nft_expr
*expr
,
66 const struct nlattr
* const tb
[])
68 struct nft_fib
*priv
= nft_expr_priv(expr
);
72 if (!tb
[NFTA_FIB_DREG
] || !tb
[NFTA_FIB_RESULT
] || !tb
[NFTA_FIB_FLAGS
])
75 priv
->flags
= ntohl(nla_get_be32(tb
[NFTA_FIB_FLAGS
]));
77 if (priv
->flags
== 0 || (priv
->flags
& ~NFTA_FIB_F_ALL
))
80 if ((priv
->flags
& (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
)) ==
81 (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
))
83 if ((priv
->flags
& (NFTA_FIB_F_IIF
| NFTA_FIB_F_OIF
)) ==
84 (NFTA_FIB_F_IIF
| NFTA_FIB_F_OIF
))
86 if ((priv
->flags
& (NFTA_FIB_F_SADDR
| NFTA_FIB_F_DADDR
)) == 0)
89 priv
->result
= ntohl(nla_get_be32(tb
[NFTA_FIB_RESULT
]));
90 priv
->dreg
= nft_parse_register(tb
[NFTA_FIB_DREG
]);
92 switch (priv
->result
) {
93 case NFT_FIB_RESULT_OIF
:
94 if (priv
->flags
& NFTA_FIB_F_OIF
)
98 case NFT_FIB_RESULT_OIFNAME
:
99 if (priv
->flags
& NFTA_FIB_F_OIF
)
103 case NFT_FIB_RESULT_ADDRTYPE
:
110 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
111 NFT_DATA_VALUE
, len
);
115 return nft_fib_validate(ctx
, expr
, NULL
);
117 EXPORT_SYMBOL_GPL(nft_fib_init
);
119 int nft_fib_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
121 const struct nft_fib
*priv
= nft_expr_priv(expr
);
123 if (nft_dump_register(skb
, NFTA_FIB_DREG
, priv
->dreg
))
126 if (nla_put_be32(skb
, NFTA_FIB_RESULT
, htonl(priv
->result
)))
129 if (nla_put_be32(skb
, NFTA_FIB_FLAGS
, htonl(priv
->flags
)))
134 EXPORT_SYMBOL_GPL(nft_fib_dump
);
136 void nft_fib_store_result(void *reg
, enum nft_fib_result r
,
137 const struct nft_pktinfo
*pkt
, int index
)
139 struct net_device
*dev
;
143 case NFT_FIB_RESULT_OIF
:
146 case NFT_FIB_RESULT_OIFNAME
:
147 dev
= dev_get_by_index_rcu(nft_net(pkt
), index
);
148 strncpy(reg
, dev
? dev
->name
: "", IFNAMSIZ
);
156 EXPORT_SYMBOL_GPL(nft_fib_store_result
);
158 MODULE_LICENSE("GPL");
159 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");